Hibernate -如何在没有N+1的情况下,在另一个@OneToMany惰性集合中获取@OneToMany惰性集合

kninwzqo  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(146)

我有这样的东西

Entity1
@Id
String id1;
@OneToMany(Fetch = LAZY)
List<Entity2> list1;
...

Entity2
@Id
String id2;
@OneToMany(Fetch = LAZY)
List<Entity3> list2;
...

Entity3
@Id
String id3;
...

我想在同一个会话中初始化list1和list2。

entity1 = (Entity1) session
                    .createCriteria(Entity1.class)                    
                    .setFetchMode("list1", FetchMode.JOIN)
                    .uniqueResult();

我想不出一个合适的方法来初始化Entity2的第二个嵌套列表,而不使用Hibernate。initialize并引发N+1查询或使用EAGER。

xv8emn3q

xv8emn3q1#

首先,不要使用遗留的Hibernate Criteria API,它已经被弃用,在Hibernate 6中被删除了。
您可以使用join提取来提取第一个集合,使用@Fetch(FetchMode.SUBSELECT)提取来提取第二个集合,但我认为这是Blaze-Persistence实体视图的完美用例。
我创建这个库是为了允许在JPA模型和自定义接口或抽象类定义的模型之间进行简单的Map,就像Spring Data Projections一样。其思想是,您可以按照自己喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)Map到实体模型。
使用Blaze-Persistence Entity-Views时,您的用例的DTO模型可能如下所示:

@EntityView(Entity1.class)
public interface Entity1Dto {
    @IdMapping
    Long getId();
    String getName();
    @Mapping(fetch = MULTISET)
    Set<Entity2Dto> getRoles();

    @EntityView(Entity2.class)
    interface Entity2Dto {
        @IdMapping
        Long getId();
        String getName();
        @Mapping(fetch = MULTISET)
        Set<Entity3Dto> getRoles();
    }
    @EntityView(Entity3.class)
    interface Entity3Dto {
        @IdMapping
        Long getId();
        String getName();
    }
}

MULTISET提取将聚合所有子行,从而避免N + 1问题。有关此问题的详细信息,请参阅文档。
查询是将实体视图应用于查询的问题,最简单的是按id查询。
Entity1Dto a = entityViewManager.find(entityManager, Entity1Dto.class, id);
Spring Data 集成允许您像Spring Data 投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<Entity1Dto> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

相关问题