热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

浅谈DetachedCriteria和Criteria的使用方法(必看)

下面小编就为大家带来一篇浅谈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
<> Restrictions.ne() 不等于 not equal

 Restrictions.gt() 大于greater than 
= Restrictions.ge() 大于等于 greater than or equal 

Criteria 这个也是必须说的东西嘛,翻译过来就是条件,标准之类的意思!和我们的离线的差不都

那么我们看看例子吧

查User表格中的所有资料

我们这个需要获取到我们的session对象哦~~线上的查询,和我们的Query类似的,但是更强大哦!

 Criteria criteria = session.createCriteria(User.class);
 List users = criteria.list();
 Iterator iterator = users.iterator();
 while(iterator.hasNext()) {
  User user = (User) iterator.next();
  System.out.println(user.getId() + user.getName());   
 }

Criteria只是个容器,如果想要设定查询条件,只要使用add()方法加入Restrictions的条件限制,例如查詢age大大于20且小于40的资料。虽然我们的SQL语句也是可以完成的,但是为了更好的封装,更多的复用代码,最好还是不要直接的书写我们的SQL语句,看到了公司封装的代码,才感觉到前辈的强大无比,复用代码的灵活性非常的高! 这里,我们可以传递无限制的Restrictions进行封装起来,非常方便的使用!

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.gt("age", new Integer(20)));
criteria.add(Restrictions.lt("age", new Integer(40)));
List users = criteria.list();

您也可以使用逻辑组合來进行查询,例如结合age等于(eq)20或(or)age为空(isNull)的条件:

一个单独的查询条件是org.hibernate.criterion.Criterion 接口的一个实例。
org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型的工厂方法。

List cats = sess.createCriteria(Cat.class)

 .add( Restrictions.like("name", "Fritz%") )

 .add( Restrictions.between("weight", minWeight, maxWeight) )

 .list();

动态关联抓取

我们的抓取模式,对于1对多的关联的形式!是不是抓取过来呢?

你可以使用setFetchMode()在运行时定义动态关联抓取的语义

List cats = sess.createCriteria(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("team.teamName", teamName, MatchMode.ANYWHERE)); 


遗憾的是上述程序报错,说是在Student中找不到team.teamName属性,这是可以理解的。那么如何通过teamName查找、、Student呢?

可以这么写:

DetachedCriteria dc = DetachedCriteria.forClass(Student.class); 
dc.createAlias("team", "t"); 
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")
     .add(Restrictions.gt(("e.age"), new Integer(20)));
List list = this.getHibernateTemplate().findByCriteria(detachedCriteria);

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

org.hibernate.criterion.Projections是 Projection 的实例工厂。

我们通过调用setProjection()应用投影到一个查询。这个的意思就是查询哪一列的意思

用来进行聚合操作,和sql中的聚合类似.求和/求平均值/统计记录数/…等等.

还有用来获取获取对象的某些属性(表字段)或属性集合.正常情况下,查询返回的是对象或对象的集合.使用投影的话就可以只返回你需要的属性值.即Hibernate不把记录封装对象了,只返回你在投影中设置的属性的值(值的集合)的数组

List results = session.createCriteria(Cat.class)

 .setProjection( Projections.rowCount() )

 .add( Restrictions.eq("color", Color.BLACK) )

 .list();
List results = session.createCriteria(Cat.class)

 .setProjection( Projections.projectionList()

  .add( Projections.rowCount() )

  .add( Projections.avg("weight") )

  .add( Projections.max("weight") )

  .add( Projections.groupProperty("color") )

 )

 .list();

在一个条件查询中没有必要显式的使用 “group by” 。某些投影类型就是被定义为 分组投影,他们也出现在SQL的group by子句中。

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

实现方式:

List results = session.createCriteria(Cat.class)

 .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )

 .addOrder( Order.asc("colr") )

 .list();
List results = session.createCriteria(Cat.class)

 .setProjection( Projections.groupProperty("color").as("colr") )

 .addOrder( Order.asc("colr") )

 .list();

alias()和as()方法简便的将一个投影实例包装到另外一个 别名的Projection实例中。简而言之, 当你添加一个投影到一个投影列表中时 你可以为它指定一个别名:

List results = 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()来表示投影:

List results = 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封装好的哦!

DetachedCriteria query = DetachedCriteria.forClass(Cat.class)

 .add( Property.forName("sex").eq('F') );

//创建一个Session

Session session = .;

Transaction txn = session.beginTransaction();

List results = query.getExecutableCriteria(session).setMaxResults(100).list();

txn.commit();

session.close();

也可以是作为子查询

DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)

 .setProjection( Property.forName("weight").avg() );

session.createCriteria(Cat.class)

 .add( Property.forName("weight).gt(avgWeight) )

 .list();

以上这篇浅谈DetachedCriteria和Criteria的使用方法(必看)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


推荐阅读
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 3年半巨亏242亿!商汤高估了深度学习,下错了棋?
    转自:新智元三年半研发开支近70亿,累计亏损242亿。AI这门生意好像越来越不好做了。近日,商汤科技已向港交所递交IPO申请。招股书显示& ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • GPT-3发布,动动手指就能自动生成代码的神器来了!
    近日,OpenAI发布了最新的NLP模型GPT-3,该模型在GitHub趋势榜上名列前茅。GPT-3使用的数据集容量达到45TB,参数个数高达1750亿,训练好的模型需要700G的硬盘空间来存储。一位开发者根据GPT-3模型上线了一个名为debuid的网站,用户只需用英语描述需求,前端代码就能自动生成。这个神奇的功能让许多程序员感到惊讶。去年,OpenAI在与世界冠军OG战队的表演赛中展示了他们的强化学习模型,在限定条件下以2:0完胜人类冠军。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • OAuth2.0指南
    引言OAuth2.0是一种应用之间彼此访问数据的开源授权协议。比如,一个游戏应用可以访问Facebook的用户数据,或者一个基于地理的应用可以访问Foursquare的用户数据等。 ... [详细]
author-avatar
好好_haohao_100
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有