hibernate的三种查询方式

Posted gxwzwyq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate的三种查询方式相关的知识,希望对你有一定的参考价值。

hibernate的查询方式常见的主要分为三种: HQL, QBC, 以及使用原生SQL查询(Session的查询)

1)Query的查询:使用HQL语句或SQL语句完成查询

2)Criteria的查询:通过方法和类中属性的关系,来设置查询条件,完成查询。

3)Session的查询:按主键查询查询,方法为get或load

一.HQL查询

? HQL(Hibernate Query Language)提供了丰富灵活的查询方式,使用HQL进行查询也是Hibernate官方推荐使用的查询方式。

? HQL在语法结构上和SQL语句十分的相同,所以可以很快的上手进行使用。使用HQL需要用到Hibernate中的Query对象,该对象专门执行HQL方式的操作。

                                                                                         查询所有示例

1
2
3
4
5
6
7
8
session.beginTransaction();
String hql = "from User"; // from 后跟的是要查询的对象,而不是表
Query query = session.createQuery(hql);
List<User> userList = query.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();
                                   带where的查询示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
session.beginTransaction();
String hql = "from User where userName = ‘James‘";
Query query = session.createQuery(hql);
List<User> userList = query.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();
/*
 在HQL中where语句中使用的是持久化对象的属性名,如上面示例中的userName。当然在HQL中也可以使用别名
*/
String hql = "from User as u where u.userName = ‘James‘";
/*
过滤条件 
在where语句中还可以使用各种过滤条件,如:=、<>、<、>、>=、<=、between、not between、
in、not in、is、like、and、or等
*/
                                                                 获取一个不完整的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
session.beginTransaction();
String hql = "select userName from User";
Query query = session.createQuery(hql);
List<Object> nameList = query.list();
for(Object obj:nameList){
   String name=(String)obj;
   System.out.println(name); } session.getTransaction().commit(); // 多个属性的话,需要用object[]接收 session.beginTransaction(); String hql = "select userName,userPwd from User"; Query query = session.createQuery(hql); List nameList = query.list(); for(Object obj:nameList){ Object[] array = (Object[]) obj; // 转成object[] System.out.println("name:" + array[0]); System.out.println("pwd:" + array[1]); } session.getTransaction().commit();
                                                          统计和分组查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
session.beginTransaction();
String hql = "select count(*),max(id) from User";
Query query = session.createQuery(hql);
List nameList = query.list();
for(Object obj:nameList){
  Object[] array = (Object[]) obj;
  System.out.println("count:" + array[0]);
  System.out.println("max:" + array[1]);
}
session.getTransaction().commit();
/*  
 该条sql语句返回的是单条数据,所以还可以这样写
 单列数据用Object,多列数据用Object[]
*/
Object[] object = (Object[]) query.uniqueResult();
System.out.println("count:" + object[0]);
System.out.println("max:" + object[1]);
                                                  更多写法
1
2
3
4
5
6
7
select distinct name from Student;
select max(age) from Student;
select count(age),age from Student group by age;
from Student order by age;
                                              HQL占位符
1
2
3
4
5
6
7
8
9
10
11
12
session.beginTransaction();
String hql = "from User where userName = ?";
Query query = session.createQuery(hql);
// 索引从0开始 
query.setString(0, "James");
List<User> userList = query.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();
                                                   HQL引用占位符
1
2
3
4
5
6
7
8
9
10
11
12
13
session.beginTransaction();
String hql = "from User where userName = :name";
Query query = session.createQuery(hql);
query.setParameter("name", "James");
List<User> userList = query.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();
                                             HQL分页
1
2
3
4
5
6
7
8
9
10
11
12
session.beginTransaction();
String hql = "from User";
Query query = session.createQuery(hql);
query.setFirstResult(0);
query.setMaxResults(2);
List<User> userList = query.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();

1.1HQL语句不只支持查询功能,还支持修改以及删除功能

  1. public void doRemove(Integer id) throws Exception {  
  2.         // 注意,使用Hibernate删除时,必须先查询对象,再删除.  
  3.         // HibernateSessionFactory.getSession().delete(findById(id));  
  4.         String hql = "DELETE FROM News AS n WHERE n.id = ?" ;  
  5.         Query query = HibernateSessionFactory.getSession().createQuery(hql);  
  6.         query.setInteger(0, id);  
  7.         query.executeUpdate();  
  8.     }  

注:使用HQL的删除可以不需要先查询,直接删除,支持一次删除多条数据
开发中的选择:1)当删除一条数据时,直接使用session.delete()就可以,因为简单,hibernate不在乎那点查询的性能;

                         2)批量删除时,使用Hql形式,这是可以提高性能的方法,因为它中间省去了查询的步骤。

1.2HQL语句修改功能

  1. public void doUpdate(News vo) throws Exception {  
  2.         // HibernateSessionFactory.getSession().update(vo);  
  3.         String hql = "UPDATE News AS n SET n.title = ?,n.content = ? WHERE n.id = ?" ;  
  4.         Query query = HibernateSessionFactory.getSession().createQuery(hql);  
  5.         query.setString(0, vo.getTitle());  
  6.         // ....其他参数一样设置  
  7.         query.executeUpdate();  
  8.     }  

开发中的选择:1)如果是直接的修改功能,选择session.update()方法;

2)如果是只修改某一字段,使用HQL方式。
注:HQL语句不支持添加,但是Query支持添加。

1.3针对HQL的查询功能,也支持写SELECT,可以通过编写SELECT,来只查询对象中某一个或某几个属性。

但是对于多种字段不同类型的查询返回的,Hibernate中只能是数组。

例如:

  1. public List testHQL() throws Exception {  
  2.         String hql = "SELECT n.id,n.title FROM News AS n";  
  3.         Query query = HibernateSessionFactory.getSession().createQuery(hql);  
  4.         return query.list();  
  5.     }  

经过测试,发现当只查询一个字段时,直接返回该类型的List集合。

但查询两个以上的字段时,返回的是List<Object[]>,每一条查询出的数据,使用Object[]来表示,这就很不方便。

  1. public void testHQL() throws Exception {  
  2.         List all = ServiceFactory.getINewsServiceInstance().testHQL();  
  3.         Object[] value1 = (Object[]) all.get(0);  
  4.         System.out.println(value1[1]);  
  5.     }  

这样使用起来很麻烦,因此在Hibernate3.2以上的版本中,提供了一个自动转换类,可以将查询出的Object[],自动转换为pojo 对象。

  1. public List testHQL() throws Exception {  
  2.         String hql = "SELECT n.id AS id,n.title AS title FROM News AS n";  
  3.         Query query = HibernateSessionFactory.getSession().createQuery(hql);  
  4.         <span style="color:#cc0000;">query  
  5.                 .setResultTransformer(new AliasToBeanResultTransformer(  
  6.                         News.class));</span>  
  7.         return query.list();  
  8.     }  

注:一般开发中不会使用这种方法,只有当表中的字段过多,但查询只需要其中的几个字段时,才会用到这种方法。

1.4Hibernate还可以将语句写到配置文件中 

  1. <query name="findAll">  
  2.         FROM News AS n WHERE n.title LIKE ?  
  3.     </query>  

通过程序读取配置文件,取得这段HQL,并生成Query对象,完成查询。 

  1. Query query = HibernateSessionFactory.getSession().getNamedQuery(  
  2.                 "findAll");  
  3.         query.setString(0, "%测试%");  
  4.         return query.list();  

这种方式在Mybatis中普遍使用,但是在Hibernate中一般很少这样做。

 

二.QBC(Query By Criteria)查询

? Criteria对象提供了一种面向对象的方式查询数据库。Criteria对象需要使用Session对象来获得。

? 一个Criteria对象表示对一个持久化类的查询。

                                        查询所有
1
2
3
4
5
6
7
8
9
10
11
session.beginTransaction();
Criteria c = session.createCriteria(User.class);
List<User> userList = c.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();

  或                        

  1. public List<News> testCriteria() throws Exception {  
  2.         // 根据传入的pojo类型,查询该类型对应的全部数据  
  3.         Criteria c = HibernateSessionFactory.getSession().createCriteria(  
  4.                 News.class);          
  5.         return c.list();  
  6.     }  
                           如果想加入查询条件,需要使用Restrictions的各种方法来完成条件的拼写。 
1
2
3
4
5
6
7
8
9
10
11
session.beginTransaction();
Criteria c = session.createCriteria(User.class);
c.add(Restrictions.eq("userName", "James"));
List<User> userList = c.list();
for(User user:userList){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();

 

 或
  1. public List<News> testCriteria() throws Exception {  
  2.         // 根据传入的pojo类型,查询该类型对应的全部数据  
  3.         Criteria c = HibernateSessionFactory.getSession().createCriteria(  
  4.                 News.class);  
  5.         // 1、WHERE id = 26  
  6.         // c.add(Restrictions.eq("id", 26));  
  7.         // 2、WHERE id > 26  
  8.         // c.add(Restrictions.gt("id", 26));  
  9.         // 3、WHERE id < 26  
  10.         // c.add(Restrictions.lt("id", 26));  
  11.         // 4、WHERE id >= 26  
  12.         // c.add(Restrictions.ge("id", 26));  
  13.         // 5、WHERE id <= 26  
  14.         // c.add(Restrictions.le("id", 26));  
  15.         // 6、WHERE id <> 26  
  16.         // c.add(Restrictions.ne("id", 26));  
  17.         // 7、WHERE title LIKE ‘%测试%‘  
  18.         // c.add(Restrictions.like("title", "%测试%"));  
  19.         // 8、WHERE id between 23 and 27  
  20.         // c.add(Restrictions.between("id", 23, 27));  
  21.         // 9、WHERE id IN (23,25,27)  
  22.         // List<Integer> allIds = new ArrayList<Integer>();  
  23.         // allIds.add(23);  
  24.         // allIds.add(25);  
  25.         // allIds.add(27);  
  26.         // c.add(Restrictions.in("id", allIds));  
  27.         // 10、复杂条件,需要使用and或or来连接各个条件  
  28.         // WHERE id = 23 OR (id <> 26 AND title LIKE ‘%测试%‘)  
  29.         c  
  30.                 .add(Restrictions.or(Restrictions.eq("id", 23), Restrictions  
  31.                         .and(Restrictions.ne("id", 26), Restrictions.like(  
  32.                                 "title", "%测试%"))));  
  33.         return c.list();  
  34.     }  

如果想加入ORDER BY排序条件,需要使用Order对象。

  1. c.addOrder(Order.desc("id"));  

如果想加入统计函数和分组函数,则需要用到Projection这个类

  1. <span style="white-space:pre">  </span>ProjectionList pro = Projections.projectionList();  
  2.         // 加入统计函数  
  3.         pro.add(Projections.rowCount());  
  4.         // 还可以加入分组条件  
  5.         pro.add(Projections.groupProperty("title"));  
  6.         c.setProjection(pro);  
                                                     Restrictions对象
1
2
3
4
5
6
7
8
9
10
11
12
方法名称                  对应SQL中的表达式
----------------------------------------------------------
Restrictions.eq       field = value
Restrictions.gt       field > value
Restrictions.lt       field < value
Restrictions.ge      field >= value
Restrictions.le       field <= value
Restrictions.between      field between value1 and value2
Restrictions.in       field in(…)
Restrictions.and      and
Restrictions.or       or
Restrictions.like     field like value
                                     示例
1
2
3
4
5
6
Criteria c = session.createCriteria(User.class);
c.add(Restrictions.like("userName", "J"));
c.add(Restrictions.eq("id", 120));
c.add(Restrictions.or(Restrictions.eq("userName", "James"),
  Restrictions.eq("userName", "Alex")));
                                 获取唯一记录
1
2
3
4
5
6
7
8
9
10
session.beginTransaction();
Criteria c = session.createCriteria(User.class);
c.add(Restrictions.eq("id", 120));
User user = (User) c.uniqueResult();
System.out.println(user.getUserName());
session.getTransaction().commit();
                                           分页
1
2
3
4
Criteria c = session.createCriteria(User.class);
c.setFirstResult(0);
c.setMaxResults(5);

                                       

1
2
3
4
5
6
7
8
9
10
session.beginTransaction();
Criteria c = session.createCriteria(User.class);
c.setProjection(Projections.sum("id"));
Object obj = c.uniqueResult();
System.out.println(obj);
session.getTransaction().commit();
                                           Projections对象
1
2
3
4
5
6
7
8
9
方法名称                          描述
-------------------------------------------------------
Projections.sum           等于SQL中聚合函数sum
Projections.avg           等于SQL中聚合函数avg
Projections.count         等于SQL中聚合函数count
Projections .distinct     去除重复记录
Projections.max           等于SQL中聚合函数max
Projections.min           等于SQL中聚合函数min
Projections .groupProperty  对指定的属性进行分组查询
                                        多个统计与分组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
session.beginTransaction();
Criteria c = session.createCriteria(User.class);
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.sum("id"));
projectionList.add(Projections.min("id"));
c.setProjection(projectionList);
// 和HQL一样,单列用Object,多列用Object[] 
Object[] obj = (Object[]) c.uniqueResult();
System.out.println("sum:" + obj[0]);
System.out.println("min:" + obj[1]);
                                     排序
1
2
3
Criteria c = session.createCriteria(User.class);
c.addOrder(Order.desc("id"));

          

                                      示例
1
2
3
4
5
6
7
8
9
10
11
12
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()示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
session.beginTransaction();
String sql = "select id,username,userpwd from t_user";
// addEntity()可以告诉Hibernate你想要封装成对象的类型,然后自动为你封装
SQLQuery query = session.createSQLQuery(sql).addEntity(User.class);
List<User> list = query.list();
for(User user : list){
  System.out.println(user.getUserName());
}
session.getTransaction().commit();
                                                uniqueResult示例
1
2
3
4
5
6
7
8
9
10
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();






以上是关于hibernate的三种查询方式的主要内容,如果未能解决你的问题,请参考以下文章

hibernate笔记--继承映射关系的三种实现方式

Hibernate注解映射联合主键的三种主要方式

Hibernate注解映射联合主键的三种主要方式

HIbernate学习笔记3 之 缓存和 对象的三种状态

ssh框架复习

Hibernate---对象的三种状态