Spring Data JPQL Query中的FetchTypes(MultipleBagFetchException)

时间:2016-05-27 13:32:47

标签: spring hibernate jpa spring-data

我正在使用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")
  • 强制使用list而不是bag

是否有人有其他解决方案,而不是将类型设置为Set

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

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

所以您的情况也许是:

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

但是在我自己的项目中尝试也不起作用。因此,另一种解决方案可能是以某种方式在@ Query-Annotation的语句中创建多个查询,以根据Vlad的建议采取行动。不确定在Annotation-Parameter本身中是否可行,还是必须要有两个带有两个注释的方法。 / 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);