【问题标题】:FetchTypes in Spring Data JPQL Query (MultipleBagFetchException)Spring Data JPQL 查询中的 FetchTypes (MultipleBagFetchException)
【发布时间】:2016-09-25 20:59:03
【问题描述】:

我正在使用Spring Data 并定义以下查询:

@Query("SELECT u FROM AppUser u LEFT OUTER JOIN fetch u.userRights a LEFT OUTER JOIN fetch u.userGroups g LEFT OUTER JOIN fetch u.userGroups ug LEFT OUTER JOIN FETCH ug.groupRights where u.login = :login")
public Optional<AppUser> findOneWithCompleteRights(@Param("login") String login);

如您所见,我想取回具有所有访问权限的登录用户。在启动spring应用程序时,它会遇到:

Caused by: javax.persistence.PersistenceException: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags

我检查了以下内容: Multiple fetches with EAGER type in Hibernate with JPA

如果我将所有@XXXToMany 类型更改为java.util.Set,它可以工作,但我想自己决定类型...

如果附加到@Query 方法,链接解决方案的其他注释(见底部)似乎会被忽略。无论如何,第二个没有意义。

  • 使用子选择 @Fetch(FetchMode.SELECT) 分别加载每个集合
  • 通过添加索引列@IndexColumn(name="LIST_INDEX") 强制使用列表而不是包

除了将类型设置为Set之外,还有其他解决方案吗?

【问题讨论】:

    标签: spring hibernate jpa spring-data


    【解决方案1】:

    我也有这个问题。 当要加载的类具有多个映射类型 List 的属性时,就会发生这种情况。

    你可以解决这个问题, 通过改变类型 AppUser.userRights 和 AppUser.userGroups 从 java.util.List 到 java.util.Set。

    【讨论】:

    • 好的,我已经在我的问题中描述了这个解决方案,并询问是否有不同的解决方案:)
    【解决方案2】:

    这里不使用 Set 而不是 List 正是 Vlad Mihalcea 在 this post 和 StackOverflow 上的一些答案中所描述的。在他的帖子中,他说要使用单独的查询。 但他提供的解决方案不是使用 Spring-Data 项目提供的 @Query-Annotation,而是使用 JPQL 语句和 entityManager。

    因此,为了实现单独的查询执行,我会想到,@Fetch(FetchMode.SELECT)(或 SUBSELECT,尚不确定差异)将是一个合适的解决方案。但不是针对@Query-Annotation,而是针对类中的属性。

    所以在你的情况下可能:

    class AppUser {
        ....
        @OneToMany
        @Fetch(FetchMode.SELECT)
        List<UserRights> userRights
        ....
    }
    
    

    但是在我自己的项目中尝试也没有奏效。因此,另一种解决方案可能是以某种方式在 @Query-Annotation 的语句中创建多个查询,以按照 Vlad 的建议行事/p>

    @Query(
        "SELECT u FROM AppUser u 
        LEFT OUTER JOIN fetch u.userRights a 
        LEFT OUTER JOIN fetch u.userGroups g 
        LEFT OUTER JOIN fetch u.userGroups ug 
        LEFT OUTER JOIN FETCH ug.groupRights where u.login = :login"
    )
    public Optional<AppUser> findOneWithCompleteRights(@Param("login") String login);
    

    【讨论】:

      猜你喜欢
      • 2014-03-05
      • 1970-01-01
      • 2015-03-18
      • 2015-12-23
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      相关资源
      最近更新 更多