OneToMany всегда загружается, даже если я использую LazyLoad - PullRequest
0 голосов
/ 01 июня 2019

У меня есть одна простая проблема, и я не уверен, почему это не работает, я хотел бы, чтобы кто-нибудь объяснил мне, что и почему я всегда получаю Роли при запросе пользователей.

По сути, я создал класс пользователяи я добавил LazyLoaded список ролей, но когда я выполняю запрос, я всегда получаю роли, а это то, что я не хочу делать.Может кто-нибудь объяснить мне, почему это происходит?

По сути, я хочу получить роли, когда захочу, насколько я понимаю, когда я в запросе использую LEFT JOIN FETCH с LazyLoad, ТОЛЬКО ЗАТЕМ все роли ДОЛЖНЫ быть получены ...

Ниже я добавил все классы и запросы, которые выбирают список ролей, даже если я не использовал 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
)

И в моем репозитории у меня есть этот Запрос, как вы можете видеть, что я не участвовал в ролях, но в любом случае я получаю список пользователей вместе со списком ролей....

@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 ]

3 голосов
/ 02 июня 2019

Ленивая инициализация работает, но из-за spring.jpa.open-in-view=true (spring default) ваша коллекция извлекается при сериализации объекта в JSON.

Короче говоря: у вас есть сеанс гибернации, связанный с текущим потоком даже в слое вида. Подробнее здесь

Я бы предложил установить spring.jpa.open-in-view=false, что делает вещи более явными и обеспечивает лучшую производительность.

Когда вы только читаете данные, я бы предложил использовать проекции Spring docs . Термин CQRS также будет полезен для вас.

3 голосов
/ 02 июня 2019

Джексон, вероятно, является виновником здесь, как это было для меня.

Вам нужно сообщить Джексону, что вы используете Hibernate.

Добавьте это к вашему pom, чтобы он мог правильно обрабатывать ленивую загрузку:

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

И создайте его Бин, добавьте его, например, в класс своего приложения:

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