上一篇我们学习了hibernate基本的概念和与springboot整合简单使用,那么这篇我门将要讲解一些高级的查询知识
和sql一样但是,但这是针对对象来操作,条件也是对象的属性
1、 第一种,用?占位符,如:
//登录(用?占位符)
public List LoginUser(UserPO up)throws Exception{
Session session = HibernateSessionFactory.getSession();
String hql = "from UserPO where name = ? and pwd= ?";
Query query = session.createQuery(hql);
query.setString(0, up.getName());
query.setString(1, up.getPwd());
List list = query.list();
session.close();
return list;
}
2、用“:+命名”占位符,如:
//登录(用":命名"占位符)
public List LoginUser2(UserPO up)throws Exception{
Session session = HibernateSessionFactory.getSession();
String hql = "from UserPO where name = :n and pwd= :p";
Query query = session.createQuery(hql);
query.setString("n", up.getName());
query.setString("p", up.getPwd());
List list = query.list();
session.close();
return list;
}
2.1、使用这种占位符还可以这样设值,如:
//登录(用":命名"占位符,用setParameter设值)
public List LoginUser3(UserPO up)throws Exception{
Session session = HibernateSessionFactory.getSession();
String hql = "from UserPO where name = :n and pwd= :p";
Query query = session.createQuery(hql);
query.setParameter("n", up.getName());
query.setParameter("p",up.getPwd());
List list = query.list();
session.close();
return list;
}
使用这种方式不需要写明映射的类型,Hibernate会通过配置自动给我们转,但是由于Hibernate有两种日期格式:Date和TIMESTAMP,所以对于日期类型必须写明映射的类型。写法:
3、按照对象进行参数绑定,如:
//登录(用":命名"占位符,用setProperties设值,命名参数必须要与被绑定的属性名相同)
public List LoginUser4(UserPO up)throws Exception{
Session session = HibernateSessionFactory.getSession();
String hql = "from UserPO where name = :name and pwd= :pwd";
Query query = session.createQuery(hql);
query.setProperties(up);
List list = query.list();
session.close();
return list;
}
/**
* 排序查询:
* 使用HQL语句,给查询结果排序
*
* HQL语句中的排序:
* order by
* asc:升序(默认值)
* desc:降序
*/
@Test
public void test4(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 按联系人ID降序排序联系人
Query query = session.createQuery("from LinkMan order by lkmId desc");
@SuppressWarnings("unchecked")
List linkMans = query.list();
transaction.commit();
for (LinkMan linkMan : linkMans) {
System.out.println(linkMan);
}
}
/**
* 分页查询
* MySQL中分页关键字:
* Limit
* limit的两个参数: 第一个参数:查询的开始记录索引。(它是从0开始的)
* 第二个参数:每次查询多少条记录。(它是固定的)
* Hibernate中涉及的方法
* setFirstResult(int firstResult):查询的开始记录索引
* setMaxResults(int maxResults):每次查询多少条记录
*/
@Test
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//1.获取Query对象
Query query = session.createQuery("from LinkMan");
//2.使用Hibernate提供的方法来设置分页条件
Integer firstResult = 0;
Integer maxResults = 2;
query.setFirstResult(firstResult);
query.setMaxResults(maxResults);
//3.执行query对象的方法
@SuppressWarnings("unchecked")
List list = query.list();
transaction.commit();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
}
/**
* 统计查询
* 其实就是在HQL语句中使用聚合函数
* count() sum() avg() max() min()
* 使用聚合函数查询时,如果没有group by,返回的结果集是一行一列的
*
* 聚合函数都不会计算为null的字段。
*
* count(*)和count(主键)是一样的。
*/
@Test
public void test6(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 查询一共有多少个联系人
Query query = session.createQuery("select count(lkmId) from LinkMan");
Long count = (Long) query.uniqueResult();
transaction.commit();
System.out.println(count);
}
/**
* 投影查询:
* 当我们查询实体对象时,并不需要所有字段信息,只查询部分,但是还想让他成为一个实体对象。其实就是用部分字段来投影出整个实体对象。
* 使用要求:
* HQL语句:
* 写法必须是 new 实体类名称(查询的字段)
* select new Customer(custId,custName) from Customer
* 注意:如果你的实体类在工程中唯一,则可以直接写类名。如果实体类在工程中不唯一,需要写全限定类名。
* 实体类要求:
* 必须在实体类中提供一个相同参数列表的构造函数。
*
*/
@Test
public void test71(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 只获取客户的ID和名字,并封装成客户对象
Query query = session.createQuery("select new Customer(custId, custName) from Customer");
@SuppressWarnings("unchecked")
List customers = query.list();
transaction.commit();
for (Customer customer : customers) {
System.out.println(customer.getCustId() + " " + customer.getCustName());
}
}
@Test
public void test72(){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
//1.获取Query对象
Query query = s.createQuery("select custId,custName from Customer ");
//2.执行query对象的方法
@SuppressWarnings("unchecked")
List
QBC(Query By Criteria)是Hibernate提供的另一种检索对象的方式,它主要由Criteria 接口、Criterion接口和Expression类组成 。Criteria接口是Hibernate API中的一个查询接口,它需要由session进行创建。Criterion是Criteria的查询条件,在Criteria中提供了add(Criterion criterion)方法来添加查询条件。
涉及的对象:
Criteria
DetachedCriteria
获取的方式:
session.createCriteria(Class clazz);参数指的是要查询的字节码
添加条件的方法:
Criteria的add方法
添加条件涉及的对象:
Restrictions
离线条件检索
DetachedCriteria 翻译为离线条件查询,因为它是可以脱离Session来使用的一种条件查询对象,我们都知道Criteria对象必须由Session对象来创建。那么也就是说必须先有Session才可以生成Criteria对象。而DetachedCriteria对象可以在其他层对条件进行封装。
这个对象也是比较有用的,尤其在SSH整合以后这个对象经常会使用 。它的主要优点是做一些特别复杂的条件查询的时候,往往会在WEB层向业务层传递很多的参数,业务层又会将这些参数传递给DAO层。最后在DAO中拼接SQL完成查询。有了离线条件查询对象后,那么这些工作都可以不用关心了,我们可以在WEB层将数据封装好,传递到业务层,再由业务层传递给DAO完成查询。
/**
* Hibernate中的查询方式:
* QBC查询:
* Query By Criteria 它是一种更加面向对象的查询方式。
* 它把查询条件都用方法封装了。里面的参数全都需要使用实体类的属性名称。
* 涉及的对象:
* Criteria
* DetachedCriteria
* 获取的方式:
* session.createCriteria(Class clazz);参数指的是要查询的字节码
* 添加条件的方法:
* Criteria的add方法。
* 添加条件涉及的对象:
* Restrictions
*
* @author Switch
*/
public class TestQBCQuery {
/**
* 基本查询:查询所有
*
* 需求:
* 查询所有客户
*/
@Test
public void test1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 条件查询
* 需求:查询客户级别是23的,客户名称带有集字的
*/
@Test
public void test2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
// 添加条件
criteria.add(Restrictions.eq("custLevel", "23"));
criteria.add(Restrictions.like("custName", "%集%"));
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 分页查询
*
* 涉及的方法:
* setFirstResult(int firstResult);
* setMaxResults(int maxResults);
* 含义和HQL是一模一样的
*/
@Test
public void test3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(2);
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List customers = criteria.list();
tx.commit();
for (Customer customer : customers) {
System.out.println(customer);
}
}
/**
* 统计查询:
* 使用QBC来添加聚合函数
*
* count() avg() min() max() sum()
*
* 涉及的方法:
* setProjections(Projection p ); 它可以加查询语句的结构。
* 涉及的类:
* Projections
* 该类中提供了一些静态方法
*/
@Test
public void test4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
criteria.setProjection(Projections.count("custId"));
//2.执行uniqueResult方法,得到结果
Long result = (Long) criteria.uniqueResult();
tx.commit();
System.out.println(result);
}
/**
* 排序查询
*
* 涉及方法:
* Criteria的addOrder方法。该方法需要一个Order对象作为参数
* Order对象有两个方法:
* desc(String propertyName):按照指定的属性名称,倒序排序。
* asc(String propertyName):按照自顶的属性名称,正序排序。
*/
@Test
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//1.获取Criteria对象
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.addOrder(Order.desc("lkmId"));
//2.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List linkMans = criteria.list();
tx.commit();
for (LinkMan linkMan : linkMans) {
System.out.println(linkMan);
}
}
/**
* 离线查询:
* 在线对象:
* Criteria对象。它的获取必须要一个可用的Session来创建。如果Session不能用,则不能创建Criteria。
* 我们使用Criteria进行的查询就是在线查询。
* 离线对象:
* 创建DetachedCriteria不需要一个可用的Session。
* 用DetachedCriteria进行的查询就叫做离线查询
* 涉及的对象
* DetachedCriteria
* 如何获取
* DetachedCriteria.forClass(Class clazz);参数的含义:要查询的实体类
* 如何设置查询条件:
* 和Criteria是一样的
*
* 在实际开发中:多条件查询用此种方式
*/
//Servlet的方法
@Test
public void doGet(){
//1.获取请求参数
String custLevel = "23";
String custName = "集";
//2.查询所有客户
DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);
dCriteria.add(Restrictions.eq("custLevel", custLevel));
dCriteria.add(Restrictions.like("custName", "%"+custName+"%"));
List cs = servicefindAllCustomer(dCriteria);
for(Customer c : cs){
//3.存入请求域中
//4.转向列表页面
System.out.println(c);
}
}
//Service的方法
public List servicefindAllCustomer(DetachedCriteria dCriteria){
return daofindAllCustomer(dCriteria);
}
//Dao中的方法
public List daofindAllCustomer(DetachedCriteria dCriteria){
Session s = HibernateUtils.getCurrentSession();
Transaction tx = s.beginTransaction();
//1.把离线对象激活
Criteria c = dCriteria.getExecutableCriteria(s);
//3.执行list方法,得到结果集
@SuppressWarnings("unchecked")
List list = c.list();
tx.commit();
return list;
}
}
采用HQL或QBC检索方式时,Hibernate生成标准的SQL查询语句,适用于所有的数据库平台,因此这两种检索方式都是跨平台的。但有的应用程序可能需要根据底层数据库的SQL方言,来生成一些特殊的查询语句。在这种情况下,可以利用Hibemate提供的原生SQL检索方式 。
session.beginTransaction();
String sql = "select id,username,userpwd from t_user";
List list = session.createSQLQuery(sql).list();
for(Object item : list){
Object[] rows = (Object[]) item;
System.out.println("id:" + rows[0] + "username:"
+ rows[1] + "userpwd:" + rows[2]);
}
session.getTransaction().commit();
addEntity()示例
session.beginTransaction();
String sql = "select id,username,userpwd from t_user";
// addEntity()可以告诉Hibernate你想要封装成对象的类型,然后自动为你封装
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
List list = query.list();
for(User user : list){
System.out.println(user.getUserName());
}
session.getTransaction().commit();
uniqueResult示例
session.beginTransaction();
String sql = "select id,username,userpwd from t_user where id = 2";
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
User user = (User) query.uniqueResult();
System.out.println(user.getUserName());
session.getTransaction().commit();
@Test
public void testSQLQuery() {
//查询所有的学生
String sql="select * from t_student";//sql语句
//.addEntity(Student.class) 要绑定实体,不然遍历不出来
Query query=session.createSQLQuery(sql).addEntity(Student.class);
List studentList=query.list();
Iterator it=studentList.iterator();
while(it.hasNext()){
//强制转换为Student类型
Student s=(Student)it.next();
System.out.println(s);
}
}
@Test
public void testSQLQuery2() {
//模糊查询
String sql="select * from t_student where student_name like :stuName and student_age=:stuAge";
Query query=session.createSQLQuery(sql).addEntity(Student.class);
query.setString("stuName", "张%");
query.setInteger("stuAge", 13);
List studentList=query.list();
Iterator it=studentList.iterator();
while(it.hasNext()){
Student s=(Student)it.next();
System.out.println(s);
}
}