Kotlin Hibernate JPA Ленивая загрузка не работает через контроллер - PullRequest
0 голосов
/ 17 декабря 2018

Я получил полный пример приложения здесь: https://github.com/MrMojoR/hibernateOnKotlin

И этот код основан на этом посте блога: https://kotlinexpertise.com/hibernate-with-kotlin-spring-boot/

Проблема в том, что пока ленивая выборка работает отличноиз интеграционного теста в отладчике есть исключение: исключение из теста

Когда я запускаю тот же код из контроллера, исключение отсутствует, загружается вся сущность: Нет исключений из контроллера

Как это возможно? Большое спасибо за вашу помощь!

В любом случае я выложу фрагменты кода:

AbstractJpaPersistable.kt

import org.springframework.data.domain.Persistable
import org.springframework.data.util.ProxyUtils
import java.io.Serializable
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.MappedSuperclass
import javax.persistence.Transient

/**
 * Abstract base class for entities. Allows parameterization of id type, chooses auto-generation and implements
 * [equals] and [hashCode] based on that id.
 *
 * This class was inspired by [org.springframework.data.jpa.domain.AbstractPersistable], which is part of the Spring Data project.
 */
@MappedSuperclass
abstract class AbstractJpaPersistable<T : Serializable> : Persistable<T> {

    companion object {
        private val serialVersionUID = -5554308939380869754L
    }

    @Id
    @GeneratedValue
    private var id: T? = null

    override fun getId(): T? {
        return id
    }

    /**
     * Must be [Transient] in order to ensure that no JPA provider complains because of a missing setter.
     *
     * @see org.springframework.data.domain.Persistable.isNew
     */
    @Transient
    override fun isNew() = null == getId()

    override fun toString() = "Entity of type ${this.javaClass.name} with id: $id"

    override fun equals(other: Any?): Boolean {
        other ?: return false

        if (this === other) return true

        if (javaClass != ProxyUtils.getUserClass(other)) return false

        other as AbstractJpaPersistable<*>

        return if (null == this.getId()) false else this.getId() == other.getId()
    }

    override fun hashCode(): Int {
        return 31
    }
}

Person.kt:

import javax.persistence.CascadeType
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.ManyToOne
import javax.persistence.OneToMany    

@Entity
class Person(
        val name: String,
        @ManyToOne(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER)
        val street: Street
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
        val zipCode: String,
        val city: String
) : AbstractJpaPersistable<Long>()

@Entity
class Street(
        @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY)
        val adresses: MutableSet<Address>
) : AbstractJpaPersistable<Long>()

PersonRepository:

import com.kotlinexpertise.hibernatedemo.model.Person
import org.springframework.data.jpa.repository.JpaRepository

interface PersonRepository : JpaRepository<Person, Long>

PersonService:

import com.kotlinexpertise.hibernatedemo.model.Person
import com.kotlinexpertise.hibernatedemo.repository.PersonRepository
import org.springframework.stereotype.Service

@Service
class PersonService(val personRepository: PersonRepository) {

    fun savePerson(person: Person) {
        personRepository.saveAndFlush(person)
    }
}

Решение:

Что это за свойство spring.jpa.open-in-view = true в Spring Boot?

Это свойство должно быть установленов false:

spring.jpa.open-in-view=false

Это не проблема Kotlin, а проблема Spring.

1 Ответ

0 голосов
/ 17 декабря 2018

Lazy полагается на тот факт, что у него доступно активное соединение.

Соединения управляются EntityManager в Hibernate.

Но ваш отладчик работает в совершенно другом потоке, поэтому он неиметь доступ к EntityManager.Отсюда и исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...