Java FetchMode.JOIN急切地获取成员列表显然会产生笛卡尔积
我正在尝试优化一个复杂的操作,涉及多个Java FetchMode.JOIN急切地获取成员列表显然会产生笛卡尔积,java,hibernate,join,Java,Hibernate,Join,我正在尝试优化一个复杂的操作,涉及多个库中的所有书籍和视频(出于保密原因,这不是实际的域) 代码最初使用标准加载所有库,然后通过迭代缓慢加载成员书籍。我基本上添加了两个FetchMode子句: List<Library> library = session .createCriteria(Library.class) .setFetchMode("books", FetchMode.JOIN) .setF
库中的所有书籍
和视频
(出于保密原因,这不是实际的域)
代码最初使用标准
加载所有库
,然后通过迭代缓慢加载成员书籍
。我基本上添加了两个FetchMode
子句:
List<Library> library = session
.createCriteria(Library.class)
.setFetchMode("books", FetchMode.JOIN)
.setFetchMode("videoShelves.videos", FetchMode.JOIN)
.list();
列表库=会话
.createCriteria(Library.class)
.setFetchMode(“books”,FetchMode.JOIN)
.setFetchMode(“VideoShelfs.videos”,FetchMode.JOIN)
.list();
第二个FetchMode
子句似乎有效,或者至少不会导致明显的问题
然而,第一种方法将库的数量从6个增加到248个。因此,在我看来,似乎每个库
对它拥有的每本书都复制一次
当将FetchMode
添加到查询中时,Hibernate在什么情况下可能会创建意外的重复实例?默认情况下,使用setFetchMode()
将导致外部联接,这是您当前观察到的。如果要在三个表之间进行内部联接
,请尝试以下操作:
List<Library> library = session.createCriteria(Library.class, "library")
.createAlias("library.book", "books")
.createAlias("books.video", "videos").
.list();
List library=session.createCriteria(library.class,“library”)
.createAlias(“library.book”、“books”)
.createAlias(“books.video”、“videos”)。
.list();
正如@TimBiegeleisen所建议的那样,这种行为的原因是外部连接。
有关更多信息,请参阅
上述链接中可能的解决方案
使用Set
列表库=。。。;
返回新的ArrayList(新的LinkedHashSet(library))代码>
使用标准。不同的\u根\u实体
结果转换器
列表库=会话
.createCriteria(Library.class)
.setFetchMode(“books”,FetchMode.JOIN)
.setFetchMode(“videoshelfs.videos”,FetchMode.JOIN)。
.setResultTransformer(标准.DISTINCT\u ROOT\u实体)
.list()代码>
但是,最好的解决方案当然不是在一个请求中获取所有数据。例如,如果您想显示一个库列表(例如,带有图书数量),您可以使用投影来只加载您想要的数据。别名不会获取相关的集合,正如您所知:)谢谢,DISTINCT\u ROOT\u ENTITY
当然做到了这一点。这是一个需要优化的遗留应用程序。它懒散地为每个图书馆加载书籍,这需要很长时间@BatchSize
对books collection有很大帮助,但它会对每个库只能访问几本书的其他用例产生负面影响。虽然这种方法在优化的查询和下游使用模式之间创建了一个隐藏的依赖关系,但该应用程序存在更严重的设计问题。投影意味着更重的重构。