虽然可以自己写Sql,但在程序中需要动态生成Sql语句时,where子句中条件是动态产生时,使用Criteria是再好不过的选择。
先看例子:
Criteria criteria=session.createCriteria(Product.class); Criterion criterion1=Restrictions.between("id", 10, 15); //Criterion接口 criteria.add(criterion1); List<Product> list=criteria.list(); for(Product p:list){ System.out.println(p.getId()+" "+p.getName()); }
输出:
Hibernate: select this_.ID as ID4_0_, this_.NAME as NAME4_0_, this_.PRICE as PRICE4_0_, this_.DESCRIPTION as DESCRIPT4_4_0_ from hib.product this_ where this_.ID between ? and ? 10 台灯3 11 台灯2 15 台灯
可以使用方法链,因为add()后仍返回当前Criteria对象。如下
List<Product> list=session.createCriteria(Product.class).add(Restrictions.between("id",10,15)).list();
1.排序 criteria.addOrder(Order.desc("id"));
2.分页
criteria.setMaxResults(3);
criteria.setFirstResult(3);
mysql产生如下语句:
Hibernate: select this_.ID as ID4_0_, this_.NAME as NAME4_0_, this_.PRICE as PRICE4_0_, this_.DESCRIPTION as DESCRIPT4_4_0_ from hib.product this_ limit ?, ?
oracle则产生:
select * from( select row_.*,rownum rownum_ from( 原始sql语句 ) row_ where rownum<=? ) where rownum_>?
3.单条记录
criteria.setMaxResults(1); Product p=(Product)criteria.uniqueResult();
4.在关联对象上增加条件
Criteria criteria=session.createCriteria(Product.class); criteria.createCriteria("category").add(Restrictions.between("id",35, 40)); //Product和Category是多对一的关系 //Prodcut类中成员 Category category;
输出:
select this_.ID as ID4_1_, this_.CATEGORY_ID as CATEGORY2_4_1_, this_.NAME as NAME4_1_, this_.PRICE as PRICE4_1_, this_.DESCRIPTION as DESCRIPT5_4_1_, category1_.ID as ID3_0_, category1_.NAME as NAME3_0_, category1_.DESCRIPTION as DESCRIPT3_3_0_ from hib.pro this_ inner join hib.category category1_ on this_.CATEGORY_ID=category1_.ID where category1_.ID between ? and ?
使用内连接查询。如果是一的一方中增加对多的一方的条件,则结果是类似的。
Criteria criteria=session.createCriteria(Category.class); criteria.createCriteria("products").add(Restrictions.between("id",1,2)); criteria.list();
输出:
Hibernate: select this_.ID as ID3_1_, this_.NAME as NAME3_1_, this_.DESCRIPTION as DESCRIPT3_3_1_, product1_.ID as ID4_0_, product1_.CATEGORY_ID as CATEGORY2_4_0_, product1_.NAME as NAME4_0_, product1_.PRICE as PRICE4_0_, product1_.DESCRIPTION as DESCRIPT5_4_0_ from hib.category this_ inner join hib.pro product1_ on this_.ID=product1_.CATEGORY_ID where product1_.ID between ? and ?
5.统计函数查询
criteria.setProjection(Projections.max("price"));
Float f=(Float)criteria.uniqueResult();
System.out.println(f);
6.多个统计值
Criteria criteria=session.createCriteria(Product.class); ProjectionList proList=Projections.projectionList(); proList.add(Projections.max("price")); proList.add(Projections.min("price")); criteria.setProjection(proList); Object[] values=(Object[])criteria.uniqueResult();
7.分组统计
Criteria criteria=session.createCriteria(Product.class); ProjectionList proList=Projections.projectionList(); proList.add(Projections.max("price")); proList.add(Projections.min("price")); proList.add(Projections.rowCount()); proList.add(Projections.groupProperty("category"));//注意这里都是指POJO类的属性名,而不是数据库列名 criteria.setProjection(proList); List<Object[]> values=criteria.list();
8.使用别名,
proList.add( Projections.alias( Projections.max("price"),"maxp") //别名的好处是下文可以用别名来限定条件 );
或者: proList.add( Projections.max("price").as("maxp"));
9.投影查询,限定列
ProjectionList proList=Projections.projectionList(); proList.add(Property.forName("price")); proList.add(Property.forName("id")); criteria.setProjection(proList);
10.使用org.hibernate.criterion.Property.forName()方法实现分组统计
proList.add(Property.forName("price").max());
proList.add(Property.forName("category").group().as("c"));
11.使用DetachedCriteria(不与Session对象绑定,独立)
//表现层,保存用户的动态查询条件 DetachedCriteria dc=DetachedCriteria.forClass(Product.class); dc.add(Restrictions.between("id", 1, 5)) .add(Restrictions.like("name", "台")); dc.addOrder(Order.desc("id")); //业务逻辑层与当前Session绑定 //获取,开启session Criteria criteria=dc.getExecutableCriteria(session); List values=criteria.list();
12.根据示例对象查询(QBE)
Product p1=new Product(); p1.setName("台"); Criteria criteria=session.createCriteria(Product.class); criteria.add(Example.create(p1)); List values=criteria.list();