即使我使用LazyLoad,也总是获取OneToMany

时间:2019-06-01 18:03:36

标签: hibernate spring-boot jpa spring-data-jpa spring-data

我有一个简单的问题,我不确定为什么这行不通,我希望有人向我解释什么以及为什么在查询用户时总是获取角色。

基本上,我创建了User类并添加了LazyLoaded Roles列表,但是当我执行查询时,我总是得到Roles,这是我不想做的事情。有人可以解释一下为什么会这样吗?

基本上,我想要实现的是获得所需的角色,我的理解是,当我在查询中使用带有LazyLoad的LEFT JOIN FETCH时,应立即获取所有角色...

下面我添加了所有类和正在获取角色列表的查询,即使我没有在查询中使用LEFT JOIN FETCH。

我有一个简单的User类,如下所示:

@Entity
@Table(name = "users")
data class User (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        var id: Long?,

        var sponsorId: Long,

        var firstName: String,

        var lastName: String,

        var photo: String,

        @Column(nullable = false, unique = true)
        var username: String,

        @JsonIgnore
        var password: String,

        @JsonIgnore
        var enabled: Boolean
) {
        @OneToMany(mappedBy = "userId", fetch = FetchType.LAZY)
        var roles: Set<UserRole> = emptySet()
}

我还有第二个简单的课程:

@Entity
@Table(name = "user_role")
data class UserRole (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        var id: Long?,

        @JsonIgnore
        var userId: Long?,

        @Enumerated(EnumType.STRING)
        var role: Role
)

在我的存储库中,我有此查询,如您所见,我没有加入CHECHED角色,但是无论如何,我都会获得用户列表以及角色列表。...

@Repository
interface UserRepository : JpaRepository<User, Long> {
    @Query("SELECT u FROM User u WHERE u.sponsorId = :sponsorId")
    fun findAllBySponsorId(@Param("sponsorId") sponsorId: Long): Set<User>

}

2 个答案:

答案 0 :(得分:3)

可以进行延迟初始化,但是由于spring.jpa.open-in-view=true (spring default),在将对象序列化为JSON时会获取您的集合。

长话短说:即使在视图层中,您也具有与当前线程绑定的休眠会话。更多here

我建议设置spring.jpa.open-in-view=false,这样可以使事情更明确,并具有更好的性能。

当您仅读取数据时,我建议使用投影Spring docs。术语CQRS也将对您有所帮助。

答案 1 :(得分:0)

杰克逊可能是我的罪魁祸首。

您需要让Jackson知道您正在使用Hibernate。

将此添加到pom中,以便它可以正确处理延迟加载:

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>

并创建一个Bean,例如将其添加到您的应用程序类中:

@Bean
public Module hibernate5Module() {
    return new Hibernate5Module();
}