【问题标题】:Kotlin Hibernate JPA Lazy fetch not working through the controllerKotlin Hibernate JPA Lazy fetch 无法通过控制器工作
【发布时间】:2019-05-17 21:54:33
【问题描述】:

我在这里有一个完整的示例应用程序:https://github.com/MrMojoR/hibernateOnKotlin

这段代码基于这篇博文:https://kotlinexpertise.com/hibernate-with-kotlin-spring-boot/

问题是,虽然延迟提取在集成测试中完美运行,但调试器中存在异常: Exception from test

当我从控制器运行相同的代码时,没有异常,整个实体被加载: No Exception from controller

怎么可能? 非常感谢您的帮助!

无论如何我都会发布代码sn-ps:

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>

人员服务:

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)
    }
}

解决方案:

What is this spring.jpa.open-in-view=true property in Spring Boot?

这个属性应该设置为false:

spring.jpa.open-in-view=false

这不是 Kotlin 问题,而是 Spring 问题。

【问题讨论】:

    标签: hibernate jpa kotlin


    【解决方案1】:

    Lazy 依赖于它有可用的活动连接这一事实。

    连接由 Hibernate 中的 EntityManager 管理。

    但是您的调试器在完全不同的线程上运行,因此它无法访问 EntityManager。因此例外。

    【讨论】:

    • 感谢您的回答,但我认为您有点误解了我的意思。我认为异常应该是启用延迟获取的预期行为。因此,在我看来,当不抛出异常时,惰性获取不起作用。
    • 我是否理解正确:(1)在运行时一切正常(2)在测试期间一切正常(3)仅由调试器引发异常?
    • 是的,同时我也发现了问题:stackoverflow.com/questions/30549489/… 无论如何,非常感谢,您的帮助将我引向了正确的方向
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 2013-10-18
    • 2014-01-03
    相关资源
    最近更新 更多