Hibernate的DetachedCriteria使用(含Criteria)

Hibernate总的来说共有三种查询方式:HQL、QBC和SQL三种

HQL(Hibernate Query Language)

SQL(Structured Query Language)

QBC(Query By Criteria)

今天重点介绍QBC

这种方式比较面向对象方式,重点是有三个描述条件的对象:Restrictions,Order,Projections。使用QBC查询,一般需要以下三个步骤

  1. 使用Session实例的createCriteria()方法创建Criteria对象;
  2. 使用工具类Restrictions的方法为Criteria对象设置查询条件,Order工具类的方法设置排序方式,Projections工具类的方法进行统计和分组;
  3. 使用Criteria对象的list()方法进行查询并返回结果。

Restrictions、Order、Projections的常用方法

Restrictions类的常用方法(设置查询条件):

返回值类型方法名称描述
SimpleExpressionRestrictions.eq等于(equal)
CriterionRestrictions.allEq使用Map,Key/Valu进行多个等于的比对
SimpleExpressionRestrictions.gt大于(great than)
SimpleExpressionRestrictions.ge大于等于(great than or equal)
SimpleExpressionRestrictions.lt小于(less than)
SimpleExpressionRestrictions.le小于等于(less than or equal)
CriterionRestrictions.between对应SQL的between
SimpleExpressionRestrictions.like对应SQL的like
CriterionRestrictions.in对应SQL的in
LogicalExpressionRestrictions.andand关系
LogicalExpressionRestrictions.oror关系
CriterionRestrictions.isNull为空
CriterionRestrictions.sqlRestrictionSQL限定查询

 

Order类的常用方法(设置排序方式):

返回值类型方法名称描述
OrderOrder.asc升序
OrderOrder.desc降序

 

Projections类的常用方法(统计和分组):

返回值类型方法名称描述
AggregateProjectionProjections.avg求平均值
CountProjectionProjections.count统计某属性的数量
CountProjectionProjections.countDistinct统计某属性不同值的数量
PropertyProjectionProjections.groupProperty指定某个属性为分组属性
AggregateProjectionProjections.max求最大值
AggregateProjectionProjections.min求最小值
ProjectionListProjections.projectionList创建一个ProjectionList对象
ProjectionProjections.rowCount查询结果集中的记录条数
AggregateProjectionProjections.sum求某属性的合计

 

QBC的查询示例和基本理解

查询历史记录表中的供应商数据

private void getEQDetachedCriteria(Class<T> clasz){
   Criteria criteria =getCurrentSession().createCriteria(VenAllHistory.class);
   criteria.add(Restrictions.eq("PointerType","Vendor"));
   criteria.addOrder(Order.desc("HistoryId"));
   ///分页查询前10条
   criteria.setFirstResult(0);
   criteria.setMaxResults(10);
   criteria.list();
}

 

复合查询

复合查询就是在原有的查询基础上在进行查询,比如有Clazz班级,包含对象属性Student,那么我们希望查询 “包含学生姓名为Bob” 的班级,那么就可以使用复合查询:

Criteria criteria = session.createCriteria(Clazz.class);Criteria criteriaInner = criteria.createCriteria(Student.class);
criteriaInner.add(Restrictions.eq("name", "Bob"));
List clazzList =  criteria.list();

DetachedCriteria、Criteria 使用区别

在常规的Web编程中,有大量的动态条件查询,即用户在网页上面自由选择某些条件,程序根据用户的选择条件,动态生成SQL语句,进行查询。
此时,我们不能在Web层使用Criteria,因为它是和Session绑定的。
DetachedCriteria可以解决这个问题,即在web层,程序员使用DetachedCriteria来构造查询条件,然后将这个 DetachedCriteria作为方法调用参数传递给业务层对象。而业务层对象获得DetachedCriteria之后,可以在session范围内直接构造Criteria,进行查询。就此,查询语句的构造完全被搬离到web层实现,而业务层则只负责完成持久化和查询的封装即可,与查询条件构造完全解耦,非常完美!

主要区别

父接口CriteriaSpecification,其下有子接口Criteria和实现类DetachedCriteria,Criteria和DetachedCriteria均可使用Criterion和Projection设置查询条件。可以设置FetchMode( 联合查询抓取的模式 ) ,设置排序方式。对于Criteria还可以设置FlushModel(冲刷 Session 的方式)和LockMode(数据库锁模式)。

Criteria和DetachedCriteria的主要区别在于创建的形式不一样,Criteria是在线的,所以它是由Hibernate Session进行创建的;而DetachedCriteria是离线的,创建时无需Session,它通过2个静态方法forClass(Class) 或 forEntityName(Name) 进行DetachedCriteria 的实例创建。

(另,Spring的框架提供了getHibernateTemplate ().findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria来返回查询结果)

所以它也称为离线条件查询,即建立一个DetachedCriteria对象,将查询的条件等指定好,然后在session.beginTransaction()后将这个对象传入。通常这个对象可以在表示层建立,然后传入业务层进行查询。

 

private void getEQDetachedCriteria(Class<T> clasz){
   DetachedCriteria criteria= DetachedCriteria.forClass(VenAllHistory.class);
   criteria.add(Restrictions.eq("PointerType","Vendor"));
   criteria.addOrder(Order.desc("HistoryId"));
   Session session = this.getCurrentSession();
   Criteria executableCriteria = criteria.getExecutableCriteria(session);
   executableCriteria.setCacheable(true);
   //return findByCriteria(criteria, -1, -1);
   return executableCriteria.list();
}

DetachedCriteria作为子查询

//主查询:人员查询
DetachedCriteria searDc =
DetachedCriteria.forClass(QymlPerson.class);

//子查询:职务人员关系表
DetachedCriteria sub =
DetachedCriteria.forClass(QymlPositionUserLink.class);
sub.add(Restrictions.eq("positionunid", positionunid));
//子查询:指定查询的列(也就是select usernuid from ....)
sub.setProjection(Property.forName("userunid"));

//主查询和子查询关联(也就是where unid in (select userunid from...) )
searDc.add(Property.forName("unid").in(sub));

在上面的例子中,用个一个类似于下面SQL 的子查询

Select * from Person a where a.unid in (select userunid from PositionUserLink b where
b.positionunid = ..)

 

动态关联抓取

我们的抓取模式,对于1对多的关联的形式!是不是抓取过来呢?
你可以使用setFetchMode()在运行时定义动态关联抓取的语义

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .setFetchMode("mate", FetchMode.JOIN)
    .setFetchMode("kittens", FetchMode.JOIN)
    .list();

投影(Projections)、聚合(aggregation)和分组(grouping)

org.hibernate.criterion.Projections是 Projection 的实例工厂。 
我们通过调用setProjection()应用投影到一个查询。这个的意思就是查询哪一列的意思 
用来进行聚合操作,和sql中的聚合类似.求和/求平均值/统计记录数/…等等. 
还有用来获取获取对象的某些属性(表字段)或属性集合.正常情况下,查询返回的是对象或对象的集合.使用投影的话就可以只返回你需要的属性值.此时,即Hibernate不把记录封装对象了,只返回你在投影中设置的属性的值(值的集合)的数组

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount() )
        //当你添加一个投影到一个投影列表中时 你可以为它指定一个别名:如
        //.add( Projections.rowCount() ,"count")
        .add( Projections.avg("weight") )
        .add( Projections.max("weight") )
        .add( Projections.groupProperty("color") )
    )
    .list();

可以选择把一个别名指派给一个投影,这样可以使投影值被约束或排序所引用。下面是两种不同的实现方式:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    //.setProjection( Projections.groupProperty("color").as("colr") )
    .addOrder( Order.asc("colr") )
    .list();

也可以使用Property.forName()来表示投影:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount().as("catCountByColor") )
        .add( Property.forName("name"))
        .add( Property.forName("weight").avg().as("avgWeight") )
        .add( Property.forName("weight").max().as("maxWeight") )
        .add( Property.forName("color").group().as("color" )
    )
    .addOrder( Order.desc("catCountByColor") )
    .addOrder( Order.desc("avgWeight") )
    .list();

 

 

 

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值