为什么当我没有设置任何级联类型时,默认情况下休眠级联



当我尝试持久化新的swipe对象时,遇到以下异常:javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: org.munch.database.models.bunch.Munch

这是我正在执行的代码:

databaseExecutor.executeAndRollbackOnFailure { entityManager ->
munch.swipes.forEach {
if (it.swipeIdKey.munchId != null) {
entityManager.persist(it)
} else if (it.updated) {
entityManager.merge(it)
}
}
entityManager.transaction.commit()
}

我还在下面粘贴了我的实体以供参考。当调用entityManager.persist(it)时,会抛出上述错误。出于某种原因,试图保留实体的OneToMany侧也是不起作用的。我已经确保CascadeTypes数组对两者都是空的,所以根据我的理解,只有我调用entityManager.persist()Swipe应该写入数据库。

如果我用merge替换persist,则操作成功,但合并导致hibernate为Munch生成额外的select,并且为Swipe生成select,这是不必要的操作。然而,合并似乎并没有将更新操作级联到Munch,它只执行2个select语句和1个insert语句。

概括一下:Hibernate似乎在级联Persist操作,而不应该级联。一种解决方案是使用merge,但使用persist应仅导致1 insert,其中merge导致2 selects + 1 insert

除了执行本机查询以插入/更新之外,我没有其他想法,但如果可能的话,我希望避免这种情况。

以下是我的实体:

Munch


@Entity
@TypeDefs(
TypeDef(
name = "list-array",
typeClass = ListArrayType::class
)
)
data class Munch(
@Column
val name: String,
@OneToMany(
fetch = FetchType.LAZY,
mappedBy = "munch",
)
val swipes: MutableList<Swipe> = mutableListOf(),
) {
@Id
@GenericGenerator(name = "generator", strategy = "uuid")
@GeneratedValue(generator = "generator")
lateinit var munchId: String
fun addSwipe(swipe: Swipe) {
swipes.add(swipe)
swipe.munch = this
}
}

Swipe

@Entity
data class Swipe(
@EmbeddedId
val swipeIdKey: SwipeIdKey,
@Column(nullable = true)
val liked: Boolean,
) : Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "munchId")
@MapsId("munchId")
lateinit var munch: Munch
@Transient
var updated = false

SwipeIdKey

@Embeddable
class SwipeIdKey : Serializable {
@Column(nullable = false)
lateinit var restaurantId: String
@Column(nullable = true)
lateinit var userId: String
@Column(nullable = true)
var munchId: String? = null
}

发生这种情况是因为您正在尝试持久化不存在的对象,所以您应该使用CascadeType.persist或首先持久化SwipeIdKey对象

最新更新