浅谈DetachedCriteria和Criteria的使⽤⽅法(必看)
在常规的Web编程中,有⼤量的动态条件查询,即⽤户在⽹页上⾯⾃由选择某些条件,程序根据⽤户的选择条件,动态⽣成SQL语句,进⾏查询。
⽐如,我记得在Facebook中可以选择⾼级查询条件,这个就是个动态的查询了塞,我们⽆法预知使⽤多少个查询,直接书写死了在我们的Dao层显然是不服和我们的意思的塞
针对这种需求,对于分层应⽤程序来说,Web层需要传递⼀个查询的条件列表给业务层对象,业务层对象获得这个条件列表之后,然后依次取出条件,构造查询语句。这⾥的⼀个难点是条件列表⽤什么来构造?传统上使⽤Map,但是这种⽅式缺陷很⼤,Map可以传递的信息⾮常有限,只能传递name和value,⽆法传递究竟要做怎样的条件运算,究竟是⼤于,⼩于,like,还是其它的什么,业务层对象必须确切掌握每条entry的隐含条件。因此⼀旦隐含条件改变,业务层对象的查询构造算法必须相应修改,但是这种查询条件的改变是隐式约定的,⽽不是程序代码约束的,因此⾮常容易出错。
DetachedCriteria可以解决这个问题,即在web层,程序员使⽤DetachedCriteria来构造查询条件,然后将这个DetachedCriteria作为⽅法调⽤参数传递给业务层对象。⽽业务层对象获得DetachedCriteria之后,可以在session范围内直接构造Criteria,进⾏查询。就此,查询语句的构造完全被搬离到web层实现,⽽业务层则只负责完成持久化和查询的封装即可,与查询条件构造完全解耦,⾮常完美!
Criteria 和 DetachedCriteria 的主要区别
在于创建的形式不⼀样, Criteria 是在线的,所以它是由 Hibernate Session 进⾏创建的,⽽ 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
<> () 不等于 not equal
<() ⼤于greater than
= () ⼤于等于 greater than or equal
< Restrictions.lt() ⼩于less than
<= Restrictions.le() ⼩于等于 less than or equal
is null Restrictions.isnull() 等于空值
is not null Restrictions.isNotNull() ⾮空值
like Restrictions.like() 字符串模式匹配
and Restrictions.and() 逻辑与
junction() 逻辑与
() 逻辑或
or Restrictions.disjunction() 逻辑或
() 逻辑⾮
in(列表) Restrictions.in() 等于列表中的某⼀个值
not in(列表) (Restrictions.in()) 不等于列表中任意⼀个值
between x and y Restrictions.between() 闭区间 xy中的任意值
not between x and (Restrictions..between()) ⼩于值X 或者⼤于值y
Criteria 这个也是必须说的东西嘛,翻译过来就是条件,标准之类的意思!和我们的离线的差不都
那么我们看看例⼦吧
查User表格中的所有资料
我们这个需要获取到我们的session对象哦~~线上的查询,和我们的Query类似的,但是更强⼤哦!
Criteria criteria = ateCriteria(User.class);
List users = criteria.list();
Iterator iterator = users.iterator();
while(iterator.hasNext()) {
User user = (User) ();
System.out.Id() + Name());
}
isnull的用法Criteria只是个容器,如果想要设定查询条件,只要使⽤add()⽅法加⼊Restrictions的条件限制,例如查詢age⼤⼤于20且⼩于40的资料。虽然我们的SQL语句也是可以完成的,但是为了更好的封装,更多的复⽤代码,最好还是不要直接的书写我们的SQL语句,看到了公司封装的代码,才感觉到前辈的
强⼤⽆⽐,复⽤代码的灵活性⾮常的⾼!这⾥,我们可以传递⽆限制的Restrictions进⾏封装起来,⾮常⽅便的使⽤!
Criteria criteria = ateCriteria(User.class);
criteria.("age", new Integer(20)));
criteria.add(Restrictions.lt("age", new Integer(40)));
List users = criteria.list();
您也可以使⽤逻辑组合來进⾏查询,例如结合age等于(eq)20或(or)age为空(isNull)的条件:
⼀个单独的查询条件是iterion.Criterion 接⼝的⼀个实例。
iterion.Restrictions类定义了获得某些内置Criterion类型的⼯⼚⽅法。
List cats = ateCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list();
动态关联抓取
我们的抓取模式,对于1对多的关联的形式!是不是抓取过来呢?
你可以使⽤setFetchMode()在运⾏时定义动态关联抓取的语义
List cats = ateCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.setFetchMode("mate", FetchMode.EAGER)
.setFetchMode("kittens", FetchMode.EAGER)
.list();
这个查询可以通过外连接抓取mate和kittens。
DetachedCriteria的关联查询
假设要通过stuName查询⼀个学⽣Student记录,可以如下:
DetachedCriteria dc = DetachedCriteria.forClass(Student.class);
dc.add(Restrictions.like("stuName", stuName, MatchMode.ANYWHERE));
如果要通过Student的Team的teamName查询⼀个Student记录,很多⼈都会这么写:
DetachedCriteria dc = DetachedCriteria.forClass(Student.class);
dc.add(Restrictions.like("amName", teamName, MatchMode.ANYWHERE));
遗憾的是上述程序报错,说是在Student中不到amName属性,这是可以理解的。那么如何通过teamName查、、Student呢?
可以这么写:
DetachedCriteria dc = DetachedCriteria.forClass(Student.class);
dc.add(Restrictions.like("t.teamName", teamName, MatchMode.ANYWHERE));
没错,就是要先建⽴team的引⽤,才能⽤team导航到teamName
Department和Employee是⼀对多关联,查询条件为:名称是“department”开发部门,部门⾥⾯的雇员年龄⼤于20岁;
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.add(Restrictions.eq("name", "department"))
.createAlias("employees", "e")
.(("e.age"), new Integer(20)));
List list = HibernateTemplate().findByCriteria(detachedCriteria);
投影(Projections)、聚合(aggregation)和分组(grouping)
iterion.Projections是 Projection 的实例⼯⼚。
我们通过调⽤setProjection()应⽤投影到⼀个查询。这个的意思就是查询哪⼀列的意思
⽤来进⾏聚合操作,和sql中的聚合类似.求和/求平均值/统计记录数/…等等.
还有⽤来获取获取对象的某些属性(表字段)或属性集合.正常情况下,查询返回的是对象或对象的集合.使⽤投影的话就可以只返回你需要的属性值.即Hibernate不把记录封装对象了,只返回你在投影中设置的属性的值(值的集合)的数组
List results = ateCriteria(Cat.class)
.setProjection( wCount() )
.add( Restrictions.eq("color", Color.BLACK) )
.list();
List results = ateCriteria(Cat.class)
.setProjection( Projections.projectionList()
.add( wCount() )
.add( Projections.avg("weight") )
.add( Projections.max("weight") )
.add( upProperty("color") )
)
.list();
在⼀个条件查询中没有必要显式的使⽤ “group by” 。某些投影类型就是被定义为分组投影,他们也出现在SQL的group by⼦句中。
可以选择把⼀个别名指派给⼀个投影,这样可以使投影值被约束或排序所引⽤。下⾯是两种不同的
实现⽅式:
List results = ateCriteria(Cat.class)
.setProjection( Projections.alias( upProperty("color"), "colr" ) )
.addOrder( Order.asc("colr") )
.list();
List results = ateCriteria(Cat.class)
.setProjection( upProperty("color").as("colr") )
.addOrder( Order.asc("colr") )
.list();
alias()和as()⽅法简便的将⼀个投影实例包装到另外⼀个别名的Projection实例中。简⽽⾔之,当你添加⼀个投影到⼀个投影列表中时你可以为它指定⼀个别名:
List results = ateCriteria(Cat.class)
.setProjection( Projections.projectionList()//⼀个查询只能使⽤⼀个投影!这⾥只能这样处理啦!
.add( wCount(), "catCountByColor" )
.add( Projections.avg("weight"), "avgWeight" )
.add( Projections.max("weight"), "maxWeight" )
.add( upProperty("color"), "color" )
)
.addOrder( Order.desc("catCountByColor") )
.addOrder( Order.desc("avgWeight") )
.list();
也可以使⽤Property.forName()来表⽰投影:
List results = ateCriteria(Cat.class)
.setProjection( Projections.projectionList()
.add( wCount().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封装好的哦!
DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
.add( Property.forName("sex").eq('F') );
//创建⼀个Session
Session session = .;
Transaction txn = session.beginTransaction();
List results = ExecutableCriteria(session).setMaxResults(100).list();
txnmit();
session.close();
也可以是作为⼦查询
DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
.setProjection( Property.forName("weight").avg() );
.add( Property.forName("weight).gt(avgWeight) )
.list();
以上这篇浅谈DetachedCriteria和Criteria的使⽤⽅法(必看)就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论