【问题标题】:Kotlin JPA Lazy RestAPI not respected不尊重 Kotlin JPA Lazy RestAPI
【发布时间】:2019-04-29 11:06:21
【问题描述】:

我有一个 Java 项目,我正在转换为 Kotlin,但是具有关系和映射 @ManytoOne 的实体存在问题。他们正在使用映射 fecht 类型 LAZY 的实体,他们是否尊重 LAZY 并执行查询。

示例:

实体父亲:

@Entity
@Table(name = "TIPOSITUACAO")
data class TipoSituacao (
    @Id
    @Column(name = "ID")
    val id: Long? = null,

    @Column(name = "DESCRICAO")
    val descricao: String? = null
)

实体儿子:

@Entity
@Table(name = "SITUACAO")
data class Situacao (

    @Id
    @Column(name = "ID")
    val id: Long,

    @Column(name = "DESCRICAO")
    val descricao: String = "",

    @Column(name = "TIPOSITUACAO_ID")
    val tipoSituacaoId: Long? = null,

    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "TIPOSITUACAO_ID", referencedColumnName = "ID", insertable = false, updatable = false)
    val tipoSituacao: TipoSituacao? = null
)

我的终点:

@RequestMapping("/api")
@RestController
class EndPoints {
    @Autowired
    private val situacaoRepository: SituacaoRepository? = null

   val situacao: List<Situacao>
        @GetMapping(value = ["/situacao"])
        get() = situacaoRepository!!.findAll()
}

返回:

[
    {
        "id": 1,
        "descricao": "SITUACAO 1.1",
        "tipoSituacaoId": 1,
        "tipoSituacao": {
            "id": 1,
            "descricao": "TIPO SITUACAO 1"
        }
    },
    {
        "id": 2,
        "descricao": "SITUACAO 1.2",
        "tipoSituacaoId": 1,
        "tipoSituacao": {
            "id": 1,
            "descricao": "TIPO SITUACAO 1"
        }
    },
    {
        "id": 3,
        "descricao": "SITUACAO 2.1",
        "tipoSituacaoId": 2,
        "tipoSituacao": {
            "id": 2,
            "descricao": "TIPO SITUACAO 2"
        }
    }
]

查询:

Hibernate: select situacao0_.id as id1_0_, situacao0_.descricao as descrica2_0_, situacao0_.tiposituacao_id as tipositu3_0_ from situacao situacao0_
Hibernate: select tiposituac0_.id as id1_1_0_, tiposituac0_.descricao as descrica2_1_0_ from tiposituacao tiposituac0_ where tiposituac0_.id=?
Hibernate: select tiposituac0_.id as id1_1_0_, tiposituac0_.descricao as descrica2_1_0_ from tiposituacao tiposituac0_ where tiposituac0_.id=?

如果我使用 @JsonIgnore@JsonManageReference@JsonBackReference em> o 儿子 TipoSituacao 直到没有返回,但查询继续执行。

我尝试使用 DTO,但同样的问题。

每次我使用 situacaoRepository.find 或者 findAll 的查询都会被执行。

有问题的项目链接:https://github.com/maxbrizolla/spring-kotlin-jpa-problem

有人可以帮助我吗?

【问题讨论】:

标签: java jpa kotlin lazy-loading many-to-one


【解决方案1】:

这里的问题是您的数据类会自动生成 toString、equals 和 hashcode 方法,这些方法会触发属性加载,因此 hibernate 会为此执行额外的必需查询。

不鼓励将数据类与 JPA 一起使用。

【讨论】:

    【解决方案2】:

    因为 kotlin 数据类是最终的,所以 hibernate 无法为惰性获取实体生成代理。 你可以把 TipoSituacao 当作普通类来做懒惰的抓取工作。


    对不起我的言辞。有一些细节我没有提到。 说话很便宜,让我给你看代码。https://github.com/javaisgood/spring-kotlin-jpa-problem

    让我们看看我做了什么。

    1. 将数据类更改为普通类并打开它及其属性。
    @Entity
    @Table(name = "TIPOSITUACAO")
    open class TipoSituacao(
            @Id
            @Column(name = "ID")
            open val id: Long? = null,
    
            @Column(name = "DESCRICAO")
            open val descricao: String? = null
    )
    
    1. 向 EndPoints 添加两种方法,一种不会触发延迟获取,另一种会触发。
    @RequestMapping("/api")
    @RestController
    class EndPoints {
        @Autowired
        private val situacaoRepository: SituacaoRepository? = null
    
        @GetMapping(value = ["/hello"])
        fun hello() = "hello!".also {
            situacaoRepository!!.findAll().forEach {
                println("situacaoId:${it.id}")
                println()
            }
        }
    
        @GetMapping(value = ["/hello2"])
        fun hello2() = "hello!".also {
            situacaoRepository!!.findAll().forEach {
                println("situacaoId:${it.id}")
                println("tipoSituacaoDescricao:${it.tipoSituacao?.descricao}")
                println()
            }
        }
    }
    

    启动应用程序。
    打个招呼。
    然后调用“hello2”。
    鞋底印花细节:

    Hibernate: select situacao0_.id as id1_0_, situacao0_.descricao as descrica2_0_, situacao0_.tiposituacao_id as tipositu3_0_ from situacao situacao0_
    situacaoId:1
    
    situacaoId:2
    
    situacaoId:3
    
    Hibernate: select situacao0_.id as id1_0_, situacao0_.descricao as descrica2_0_, situacao0_.tiposituacao_id as tipositu3_0_ from situacao situacao0_
    situacaoId:1
    Hibernate: select tiposituac0_.id as id1_1_0_, tiposituac0_.descricao as descrica2_1_0_ from tiposituacao tiposituac0_ where tiposituac0_.id=?
    tipoSituacaoDescricao:TIPO SITUACAO 1
    
    situacaoId:2
    tipoSituacaoDescricao:TIPO SITUACAO 1
    
    situacaoId:3
    Hibernate: select tiposituac0_.id as id1_1_0_, tiposituac0_.descricao as descrica2_1_0_ from tiposituacao tiposituac0_ where tiposituac0_.id=?
    tipoSituacaoDescricao:TIPO SITUACAO 2
    

    现在您将看到延迟提取起作用了。

    【讨论】:

      猜你喜欢
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      • 2012-10-22
      • 2019-08-13
      • 2018-12-09
      • 2020-05-06
      • 2013-10-18
      • 1970-01-01
      相关资源
      最近更新 更多