【问题标题】:Recreating table using JPA, Kotlin and @ElementCollection使用 JPA、Kotlin 和 @ElementCollection 重新创建表
【发布时间】:2020-07-23 11:25:48
【问题描述】:

我有一个奇怪的问题。这是我的代码:

@Table(name = "rank")
@Entity
data class Rank(
        @Id
        private val id: String,

        @Embedded
        private var rankValue: RankValue,

        @ElementCollection
        @CollectionTable(
                name="rank_change",
                joinColumns = [JoinColumn(name = "rank_id")]
        )
        private val set: MutableSet<RankChange>

) {

    fun calculateDifference(loseRank: Rank, rankPolicy: RankPolicy): Double {
        return rankPolicy.calculateRankDifference(rankValue.value, loseRank.rankValue.value)
    }

    fun addChange(difference: Double, now: LocalDateTime, sparringId: String? = null) {
        rankValue = rankValue.apply(difference)
        set.add(RankChange(date = now, value = difference, sparringId = sparringId))
    }
}
@Embeddable
data class RankChange(
        @Column(name = "date")
        private val date: LocalDateTime,

        @Column(name = "value")
        private val value: Double,

        @Column(name = "sparring_id")
        private val sparringId: String? = null
)

当我向MutableSet&lt;RankChange&gt; 添加元素时,休眠删除“rank_change”表并逐行插入。也许我应该实现 equals 和哈希码合同或使用 MutableList&lt;T&gt; 并添加 @OrderColumn 注释?但我真的不需要订单。

【问题讨论】:

  • 这有什么奇怪的? ElementCollection 中的元素没有标识,因此 JPA 没有 ElementCollection 中“先前存在”元素的概念
  • 好的,但是我可以改变这种行为吗?我的情况是我只想插入行。
  • 解决方案非常简单:为对象赋予身份,即使它们成为实体并赋予它们id
  • 好吧,但你不觉得这是人为的吗? RankChange 不是实体 - 它只是值对象。
  • 身份与否,正是实体与值对象的区别。你本质上是在说:'这个对象不是一个实体,它不需要身份',同时,'JPA 需要识别这些对象来判断它们中的哪些先前存在,然后只插入新的,而不重写所有的行。你也不能一边吃蛋糕一边吃

标签: hibernate kotlin jpa collections hibernate-mapping


【解决方案1】:

@ElementCollection 的行为类似于单向 @OneToMany,从这个意义上说,它会删除所有行并从内存中的集合中一一插入元素。

为避免这种情况,您可以创建一个单独的实体来保存元素并使 (@OneToMany - @ManyToOne) 关系是双向的(mappedBy 在父端,@JoinColumn 在子端)。

【讨论】:

  • 那么您是否建议将 RankChange 从 embeddable 更改为 entity ?
  • 好的,是否可以在不重新创建数据的情况下使用 @ElementCollection ? :D
  • @Bambelal 不,这就是重点。对此集合没有脏检查,并且这些对象的身份在数据库和 java 中是不同的。请注意,数据库不知道 java 的 equals 是什么意思,并且由于 hibernate 不会跟踪没有 id 的元素的更改,因此只是使用当前状态在数据库中重新创建集合
  • 这个呢:vladmihalcea.com/… ?
  • @Bambelal 注意注释:“因此,JPA 提供者很可能会假设 Embeddable 中所有字段的组合是唯一的,结合外键 (JoinColumn(s)) . 然而,这可能效率低下,或者如果 Embeddable 很大或很复杂则不可行。这是一个假设,是特定于供应商的,并非总是如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 2016-11-18
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
相关资源
最近更新 更多