你的位置:首页 > Java教程

[Java教程]Hibernate之criteria查询


  以前写hibernate查询的时候都是万年不变的HQL语句查询,实在不行的就返璞归真进行SQL查询,这两天写代码的时候见到了criteria的查询方式,觉得挺好使,就在网上查查资料,项目里面的功能是完成了,但是对这个criteria的使用还是不是很熟练,建个小工程搭个hibernate,一边看资料一边做测试顺便写个博客记录一下,一举三得有木有。

  Hibernate 定义了CriteriaSpecification接口规范用来完成面向对象的条件查询,Criteria 就是CriteriaSpecification的子接口。使用criteria时,你不需要去关心SQL语句,我想这对于SQL语句不太好的人来说是个最大的好处,好了废话不多说,下面进入主题。

  1、创建Criteria

  Criteria的实现是离不开session的,也就是说Criteria的生命周期随着session的生命周期的结束而结束,在使用Criteria进行查询的时候,每次都要在执行时期动态建立物件,并且加入各种查询条件,如果session回收了,那么Criteria也跟着回收。

  Criteria的创建如下:

Criteria criteria = session.createCriteria(User1.class);

User1.class表示你要查询的那个实体类。

 

  2、Criteria查询

2.1

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

上述的方式就是Criteria的查询方式,创建好Criteria之后,只要使用Criteria.list()方法即可查询到你要查询的实体的数据集合,可以看一下hibernate发出的sql语句:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_

这个跟我们写HQL语句查询时hibernate发出的sql语句是一样。

2.2

  但是上面的查询是对查询出了全部的数据,有时候这并不是我们想要的,比如说我现在想查出姓张的用户?这时候就需要使用Criteria方式添加条件了,先看一个代码演示:

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    criteria.add(Restrictions.like("name", "%张%"));    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

  此时的查询结果就是名字中带有张字的用户,上面说的姓张的用户并不准确,这就是一个模糊查询,like像的意思,也就是说在告诉criteria在查询的时候给我找出来名字带张字的,看我不揍死他们,就这意思。

此时控制台发出的sql语句如下:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where this_.username like ?

要注意的地方有几个:第一,like后面的两个参数,第一个参数是实体类中对应的要查询的字段,第二个参数是查询的条件。

          第二,模糊查询可以用like,但是等于查询就是eq、大于等于是ge、between表示两者之间等等,这个在使用的时候需要注意一下,不同的查询使用不同的可以叫做方法吧。

          第三,添加条件的时候都是使用的criteria.add(),这个方法是没有什么变化的。

          第四,Restrictions是一个工具类,提供了大量的静态方法,比如上面的like(),eq()等。

 

2.3

上面的查询条件是只有一个,那如果现在我有多个查询条件怎么办呢?这个也好办,使用多个criteria.add()方法来满足多条件的查询,并且这多个条件之间属于and的关系,如下所示:

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    criteria.add(Restrictions.like("name", "%张%"));  criteria.add(Restrictions.eq("password", "123"));    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

上面的查询什么意思呢?意思就是在查找名字中带有张字的同时还要满足密码是123的,两个条件之间属于并列关系,可以看一下hibernate发出的查询语句:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where this_.username like ? and this_.pwd=?

 

2.4

  现在需求又变了,怎么变了呢?我现在不查名字里面带张字的了,我现在知道俩密码,一个123,一个234,就查密码是123或者234的用户,这时候怎么查啊?俩条件我写俩criteria.add()方法吗?但是这俩是属于and关系啊,怎么搞?看下面的代码:

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    //criteria.add(Restrictions.like("name", "%张%"));  //criteria.add(Restrictions.eq("password", "123"));    criteria.add(Restrictions.or(      Restrictions.eq("password", "123"),       Restrictions.eq("password", "234")));    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

再看一下hibernate发出的sql语句:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where (this_.pwd=? or this_.pwd=?)

可以看到sql语句最后是pwd=? or pwd = ?,进行的是或查询,怎么实现的呢?就是Restrictions.or()方法,表示或的意思,里面的两个参数又是两个表达式,between操作与or操作差不多,大家试一下就会了,我就不再废话了。

 

2.5

列一下常用的常用的几个Restrictions方法:

  Restrictions.eq 等于
  Restrictions.allEq 使用Map,使用key/value进行多个等于的比对
  Restrictions.gt 大于 >
  Restrictions.ge 大于等于 >=
  Restrictions.lt 小于 <
  Restrictions.le 小于等于 <=
  Restrictions.between 对应SQL的BETWEEN子句
  Restrictions.like 对应SQL的LIKE子句
  Restrictions.in 对应SQL的in子句
  Restrictions.and and关系
  Restrictions.or or关系

 

3.criteria 排序、统计、分组等功能

3.1 排序

在使用criteria查询结果集的时候是可以对所查询的数据进行排序的,怎么做呢?看下面:

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    criteria.addOrder(Order.asc("name"));    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

hibernate发出的sql语句:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ order by this_.username asc

可以看到是根据用户名进行正序排序,如果是倒序排列呢,只需要把asc换成desc就可以了,就是这么任性,但是要注意,此时添加的排序条件是使用的是criteria.addOrder()方法,而不是criteria.add().

3.2 伪分页

  为什么叫伪分页呢,我这里就是做一个简单的演示操作,跟分页扯不上什么关系,只不过查询方法类似于分页的查询方法而已,所以我起名叫伪分页,不过这个应该有具体的名字吧,不过我也不知道到底叫什么,就随便叫吧,大家看了代码就知道我说的是什么了。

 

@Test  public void test() {      Criteria criteria = session.createCriteria(User1.class);    //criteria.addOrder(Order.asc("name"));  criteria.setFirstResult(1);  criteria.setMaxResults(3);    List<User1> list = criteria.list();    for(User1 u: list){    System.out.println(u.toString());  }      }

 

上sql语句:

Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ limit ?, ?

看了上面的代码大家有没有觉得跟写分页时候的从第几条记录开始,每次显示多少条记录很像。

 

    今天有事,先总结到这,下次再继续总结。