文档章节

Hibernate Criteria 查询 出现重复实体

北有风雪
 北有风雪
发布于 2017/02/16 13:50
字数 757
阅读 29
收藏 0

Hibernate Criteria 查询 出现重复实体

Role与RoleResourcePermission是OneToMany关系,通过Hibernate Criteria查询Role对象时,OUT LEFT JOIN导致Role对象重复

思路

Hibernate的关联查询分为查询和实体包装,left join查询出来的结果本身是不重复的,或者说是只有多端实体不重复,但是Hibernate在做完实体包装之后,因为多端实体被包装成集合,导致生成的最终实体是重复的

解决方法

1、使用DISTINCT_ROOT_ENTITY

Criteria criteria = session.createCriteria(Role.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.list();

通过设置根实体级别的排重得到不重复的实体集合,但是这种方式引入了新的问题。

引入的新问题 1

思路中提到,Hibernate的关联查询分两步,先查询后包装,在使用元查询做分页的时候,maxResults在查询时就已确定,而distinct entity是对实体的操作,所以会导致实际查出来的实体数比maxResults的预期要少。所以在使用这种方式进行查询的时候,不推荐使用元查询的maxResults字段进行分页。

2、设置FetchType.LAYZ

    @OneToMany(fetch = FetchType.LAYZ, mappedBy = "role")

将fetch方式改为懒加载,那么在关联查询的时候,多端对象不会被查出来,只会在用到的时候才会进行查询,这就相当于不进行left join查询了,那么得到的结果也是不重复的,但是这种方式也会引入新的问题。

引入的新问题 2

Hibernate的懒加载是session级别的,目的是用来提升性能。当在同一个session下,直接查询Role实体,实体中不包含多端对象,当需要获取多端对象时Hibernate才会从数据库中进行查询;如果在一个session中查询出Role实体,但是在session关闭之后再去获取多端对象的话,Hibernate则会抛出:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.teemo.entity.Role.resourcePermissions, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:563)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:205)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:542)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:133)
    at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:163)

3、取消实体之间的非必要join

取消实体之间的非必要join,只在用到的时候才去查询子实体,这样做的好处是既不影响分页,又提升了查询性能,不好的地方是可能需要多次查询

以Role和RoleResourcePermission取消关联关系为例:

  1. 取消Role和RoleResourcePermission的OneToMany关联
  2. 查询Role实体直接返回Role实体集合
  3. 在使用Role实体时,如果需要用到RoleResourcePermission,则根据roleId自行获取RoleResourcePermission集合
  4. 如果不需要使用RoleResourcePermission的话,则不需要进行查询

以上方式因为每次查询都是无关联的实体,所以也就不需要Distinct Entity操作了,即使使用Criteria元查询也是可以使用maxResults进行分页的,由于多端实体只在需要的时候才会加载,所以也算是懒加载的一种方式

© 著作权归作者所有

共有 人打赏支持
北有风雪
粉丝 2
博文 33
码字总数 55091
作品 1
程序员
关于Hibernate的Criteria查询

如同大家所了解的Hibernate框架技术是现今的主流SSH之一的技术,Cirteria查询诞生让的我们看到一种全新的方式(不得不说独特),不用自己编写的SQL或HQL(Hibernate Query Languae)语句 (这...

梦游先生
2013/12/10
0
0
Hibernate Criteria 用法

Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria 。Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样, Criteria 是在...

chailink
2013/07/20
0
1
Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加

Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略; 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja...

别叫小伙
2017/03/09
0
0
Hibernate 性能优化法则

原文同步至: Hibernate 是 Java EE 应用中流行的 JPA 框架,简单易用,但很多使用过 Hibernate 的开发者都普遍反映 Hibernate 性能低下。究其原因,还是使用者没有对 Hibernate 进行过深入理...

waylau
2016/04/18
184
0
Hibernate - DetachedCriteria 的完整用法

现在对 Hibernate的Criteria 的用法进行总结: Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria 。 Criteria 和 DetachedCriteria...

heroShane
2014/03/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Laravel UNION联合查询并分页

$xk = DB::table('xiaokes')->select(['id','xk_name as name','xk_teacher_id as tid','ke_type','created_at']) ->where('xk_teacher_id',$id); $query = DB::......

一只懒猫-
31分钟前
1
0
187 修改centos的密码

先登录

Lucky_Me
38分钟前
3
0
通过Timer类实现App 启动页停留三秒效果

Timer timer = new Timer(); //参数1:每次执行的任务代码 参数2:延时多少毫秒执行 参数3:任务间隔 单位:毫秒 timer.schedule(new TimerTask() { @Over...

lanyu96
44分钟前
0
0
pip更改下载源设置

任何一个信息都可以把人分为两类,知道的和不知道的。有些我们已知的信息,自己觉得很平常,却可能对另一些不知道的人来说很有用处。 比如今天要说的这个小技巧,我自己原以为不值一提,网上...

crossin
45分钟前
1
0
css预加载

css /* 预加载图片,挂在body上 */.preload-img:after{ content:""; background: url(../images/new/full_bg2.jpg) no-repeat -10000px -1000px;} js $(function(){ /......

红羊在厦门
52分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部