Kotlin Hibernate JPA Lazy提取无法通过控制器工作

时间:2018-12-17 14:00:57

标签: hibernate jpa kotlin

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

并且此代码基于以下博客文章:https://kotlinexpertise.com/hibernate-with-kotlin-spring-boot/

问题是,尽管懒惰提取在集成测试中可以正常工作,但调试器中存在异常: Exception from test

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

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

无论如何,我都会发布代码段:

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

解决方案:

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

此属性应设置为false:

spring.jpa.open-in-view=false

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

1 个答案:

答案 0 :(得分:0)

懒惰依赖于它具有活动连接可用的事实。

连接由Hibernate中的EntityManager管理。

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