Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java FetchMode.JOIN急切地获取成员列表显然会产生笛卡尔积_Java_Hibernate_Join - Fatal编程技术网

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有很大帮助,但它会对每个库只能访问几本书的其他用例产生负面影响。虽然这种方法在优化的查询和下游使用模式之间创建了一个隐藏的依赖关系,但该应用程序存在更严重的设计问题。投影意味着更重的重构。