浅谈DetachedCriteria和Criteria的使用方法(必看)
在常规的Web编程中,有大量的动态条件查询,即用户在网页上面自由选择某些条件,程序根据用户的选择条件,动态生成SQL语句,进行查询。
比如,我记得在Facebook中可以选择高级查询条件,这个就是个动态的查询了塞,我们无法预知使用多少个查询,直接书写死了在我们的Dao层显然是不服和我们的意思的塞
针对这种需求,对于分层应用程序来说,Web层需要传递一个查询的条件列表给业务层对象,业务层对象获得这个条件列表之后,然后依次取出条件,构造查询语句。这里的一个难点是条件列表用什么来构造?传统上使用Map,但是这种方式缺陷很大,Map可以传递的信息非常有限,只能传递name和value,无法传递究竟要做怎样的条件运算,究竟是大于,小于,like,还是其它的什么,业务层对象必须确切掌握每条entry的隐含条件。因此一旦隐含条件改变,业务层对象的查询构造算法必须相应修改,但是这种查询条件的改变是隐式约定的,而不是程序代码约束的,因此非常容易出错。
DetachedCriteria可以解决这个问题,即在web层,程序员使用DetachedCriteria来构造查询条件,然后将这个DetachedCriteria作为方法调用参数传递给业务层对象。而业务层对象获得DetachedCriteria之后,可以在session范围内直接构造Criteria,进行查询。就此,查询语句的构造完全被搬离到web层实现,而业务层则只负责完成持久化和查询的封装即可,与查询条件构造完全解耦,非常完美!
Criteria和DetachedCriteria的主要区别
在于创建的形式不一样,Criteria是在线的,所以它是由HibernateSession进行创建的,而DetachedCriteria是离线的,创建时无需Session.
DetachedCriteria的创建
DetachedCriteria提供了2个静态方法,进行DetachedCriteria实例的创建。
forClass(Class)
forEntityName(Name)
Spring的框架提供了对于离线查询的支持,非常的简单的使用那些方法
Spring的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria)方法可以很方便地根据DetachedCriteria来返回查询结果。Criteria的子类就是DetachedCriteria我们可以简单的使用就好了。
使用到了这些我们就不得不说Restrictions
是产生查询条件的工具类。Restrictions表达式如下
HQL运算符QBC运算符含义
=Restrictions.eq()等于equal
<>Restrictions.ne()不等于notequal
Restrictions.gt()大于greaterthan =Restrictions.ge()大于等于greaterthanorequalCriteria这个也是必须说的东西嘛,翻译过来就是条件,标准之类的意思!和我们的离线的差不都
那么我们看看例子吧
查User表格中的所有资料
我们这个需要获取到我们的session对象哦~~线上的查询,和我们的Query类似的,但是更强大哦!
Criteriacriteria=session.createCriteria(User.class); Listusers=criteria.list(); Iteratoriterator=users.iterator(); while(iterator.hasNext()){ Useruser=(User)iterator.next(); System.out.println(user.getId()+user.getName()); }Criteria只是个容器,如果想要设定查询条件,只要使用add()方法加入Restrictions的条件限制,例如查詢age大大于20且小于40的资料。虽然我们的SQL语句也是可以完成的,但是为了更好的封装,更多的复用代码,最好还是不要直接的书写我们的SQL语句,看到了公司封装的代码,才感觉到前辈的强大无比,复用代码的灵活性非常的高!这里,我们可以传递无限制的Restrictions进行封装起来,非常方便的使用!
Criteriacriteria=session.createCriteria(User.class); criteria.add(Restrictions.gt("age",newInteger(20))); criteria.add(Restrictions.lt("age",newInteger(40))); Listusers=criteria.list();您也可以使用逻辑组合來进行查询,例如结合age等于(eq)20或(or)age为空(isNull)的条件:
一个单独的查询条件是org.hibernate.criterion.Criterion接口的一个实例。
org.hibernate.criterion.Restrictions类定义了获得某些内置Criterion类型的工厂方法。Listcats=sess.createCriteria(Cat.class) .add(Restrictions.like("name","Fritz%")) .add(Restrictions.between("weight",minWeight,maxWeight)) .list();动态关联抓取
我们的抓取模式,对于1对多的关联的形式!是不是抓取过来呢?
你可以使用setFetchMode()在运行时定义动态关联抓取的语义
Listcats=sess.createCriteria(Cat.class) .add(Restrictions.like("name","Fritz%")) .setFetchMode("mate",FetchMode.EAGER) .setFetchMode("kittens",FetchMode.EAGER) .list();这个查询可以通过外连接抓取mate和kittens。
DetachedCriteria的关联查询
假设要通过stuName查询一个学生Student记录,可以如下:
DetachedCriteriadc=DetachedCriteria.forClass(Student.class); dc.add(Restrictions.like("stuName",stuName,MatchMode.ANYWHERE));如果要通过Student的Team的teamName查询一个Student记录,很多人都会这么写:
DetachedCriteriadc=DetachedCriteria.forClass(Student.class); dc.add(Restrictions.like("team.teamName",teamName,MatchMode.ANYWHERE));
遗憾的是上述程序报错,说是在Student中找不到team.teamName属性,这是可以理解的。那么如何通过teamName查找、、Student呢?可以这么写:
DetachedCriteriadc=DetachedCriteria.forClass(Student.class); dc.createAlias("team","t"); dc.add(Restrictions.like("t.teamName",teamName,MatchMode.ANYWHERE));没错,就是要先建立team的引用,才能用team导航到teamName
Department和Employee是一对多关联,查询条件为:名称是“department”开发部门,部门里面的雇员年龄大于20岁;
DetachedCriteriadetachedCriteria=DetachedCriteria.forClass(Department.class); detachedCriteria.add(Restrictions.eq("name","department")) .createAlias("employees","e") .add(Restrictions.gt(("e.age"),newInteger(20))); Listlist=this.getHibernateTemplate().findByCriteria(detachedCriteria);投影(Projections)、聚合(aggregation)和分组(grouping)
org.hibernate.criterion.Projections是Projection的实例工厂。
我们通过调用setProjection()应用投影到一个查询。这个的意思就是查询哪一列的意思
用来进行聚合操作,和sql中的聚合类似.求和/求平均值/统计记录数/…等等.
还有用来获取获取对象的某些属性(表字段)或属性集合.正常情况下,查询返回的是对象或对象的集合.使用投影的话就可以只返回你需要的属性值.即Hibernate不把记录封装对象了,只返回你在投影中设置的属性的值(值的集合)的数组
Listresults=session.createCriteria(Cat.class) .setProjection(Projections.rowCount()) .add(Restrictions.eq("color",Color.BLACK)) .list();Listresults=session.createCriteria(Cat.class) .setProjection(Projections.projectionList() .add(Projections.rowCount()) .add(Projections.avg("weight")) .add(Projections.max("weight")) .add(Projections.groupProperty("color")) ) .list();在一个条件查询中没有必要显式的使用“groupby”。某些投影类型就是被定义为分组投影,他们也出现在SQL的groupby子句中。
可以选择把一个别名指派给一个投影,这样可以使投影值被约束或排序所引用。下面是两种不同的
实现方式:
Listresults=session.createCriteria(Cat.class) .setProjection(Projections.alias(Projections.groupProperty("color"),"colr")) .addOrder(Order.asc("colr")) .list();Listresults=session.createCriteria(Cat.class) .setProjection(Projections.groupProperty("color").as("colr")) .addOrder(Order.asc("colr")) .list();alias()和as()方法简便的将一个投影实例包装到另外一个别名的Projection实例中。简而言之,当你添加一个投影到一个投影列表中时你可以为它指定一个别名:
Listresults=session.createCriteria(Cat.class) .setProjection(Projections.projectionList()//一个查询只能使用一个投影!这里只能这样处理啦! .add(Projections.rowCount(),"catCountByColor") .add(Projections.avg("weight"),"avgWeight") .add(Projections.max("weight"),"maxWeight") .add(Projections.groupProperty("color"),"color") ) .addOrder(Order.desc("catCountByColor")) .addOrder(Order.desc("avgWeight")) .list();也可以使用Property.forName()来表示投影:
Listresults=session.createCriteria(Cat.class) .setProjection(Projections.projectionList() .add(Projections.rowCount().as("catCountByColor")) .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();DetachedCriteria类使你在一个session范围之外创建一个查询,并且可以使用任意的Session来执行它。
也可以使用spring封装好的哦!DetachedCriteriaquery=DetachedCriteria.forClass(Cat.class) .add(Property.forName("sex").eq('F')); //创建一个Session Sessionsession=.; Transactiontxn=session.beginTransaction(); Listresults=query.getExecutableCriteria(session).setMaxResults(100).list(); txn.commit(); session.close();也可以是作为子查询
DetachedCriteriaavgWeight=DetachedCriteria.forClass(Cat.class) .setProjection(Property.forName("weight").avg()); session.createCriteria(Cat.class) .add(Property.forName("weight).gt(avgWeight)) .list();以上这篇浅谈DetachedCriteria和Criteria的使用方法(必看)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。