Issue
i'm using spring data jpa. when i want to clone an entity with one to many relation,
fun clonePurchaseOrder(purchaseOrder: PurchaseOrder, operator: String): PurchaseOrder {
//prepare data
val items = purchaseOrder.items
//detach
items.forEach { entityManager.detach(it) }
purchaseOrder.costRevise?.let { entityManager.detach(it) }
entityManager.detach(purchaseOrder)
purchaseOrder.id = null
//modify
items.forEach {
it.id = null
it.purchaseOrder = purchaseOrder
}
//modify purchaseOrder
val now = Date()
return purchaseOrder.apply {
number = null
costRevise = null
paymentHistories = mutableListOf()
status = PurchaseOrder.Status.DRAFT
createTime = now
creator = operator
modifyTime = now
submitTime = null
submitOperator = null
closeOperator = null
closeReason = null
closeTime = null
}.save()
}
i set the purchaseOrder id =null, and each items id = null, but get the follw exception
org.springframework.orm.jpa.JpaSystemException: Don't change the reference to a collection with delete-orphan enabled : com.hkmci.web.bms2.backend.database.entity.PurchaseOrder.items; nested exception is org.hibernate.HibernateException: Don't change the reference to a collection with delete-orphan enabled : com.hkmci.web.bms2.backend.database.entity.PurchaseOrder.items
here is purchaseOrder entity and items entity
@Entity
class PurchaseOrder(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null,
...(other Column)
@OneToMany(mappedBy = "purchaseOrder", cascade = [CascadeType.ALL], orphanRemoval = true)
var items: MutableList<PurchaseOrderItem> = mutableListOf(),
...(other Column)
@Entity
class PurchaseOrderItem(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null,
@ManyToOne(fetch = FetchType.LAZY)
var purchaseOrder: PurchaseOrder,
...(other column)
can any one help with this?
Solution
//clone a purchaseOrder, new purchaseOrder will be reset to Draft
fun clonePurchaseOrder(purchaseOrder: PurchaseOrder, operator: String): PurchaseOrder {
//clear all relationships
purchaseOrder.costRevise?.let { entityManager.detach(it) }
purchaseOrder.items.forEach {
entityManager.detach(it)
it.id = null
}
purchaseOrder.paymentHistories.forEach {
entityManager.detach(it)
}
entityManager.detach(purchaseOrder)
//reset all fields
val now = Date()
purchaseOrder.apply {
id = null
number = null
costRevise = null
items = items.toMutableList()
paymentHistories = mutableListOf()
status = PurchaseOrder.Status.DRAFT
createTime = now
creator = operator
modifyTime = now
submitTime = null
submitOperator = null
closeOperator = null
closeReason = null
closeTime = null
}
//save
return purchaseOrderRepository.save(purchaseOrder)
}
No need to reassociate items and purchaseOrder , just clear all relationships, set id = null and save
Answered By - funnyJack
Answer Checked By - Marie Seifert (JavaFixing Admin)