@OneToMany(mappedBy = "recruitmentBusiness", orphanRemoval = true, cascade = [CascadeType.REMOVE])
var needCertificateList: MutableSet<CertificateUsage> = HashSet()
protected set
@Entity
@Table(name = "ceritifcate_usage")
@IdClass(CertificateUsageIdClass::class)
class CertificateUsage(
certificate: Certificate,
recruitmentBusiness: RecruitmentBusiness
):BaseTimeEntity(), Persistable<String>, Serializable {
@Id
@ManyToOne
@JoinColumn(name = "certificate_id")
val certificate: Certificate = certificate
@Id
@ManyToOne
@JoinColumn(name = "recruitment_business_id")
var recruitmentBusiness: RecruitmentBusiness? = recruitmentBusiness
protected set
fun removeNeedCertificate(certificateName: String) {
this.needCertificateList.filter {
it.certificate.name == certificateName
}.map {
this.needCertificateList.remove(it)
}
}
기존, 위와 같이 모집공고 Entity에서 Certificate 삭제를 관리하던 중, Certificate이 삭제되지 않는 버그를 발견했습니다.
JPA에선 변경된 자식을 먼저 insert 하고 삭제시킨 자식은 상위 객체에 대한 fk값을 NULL로 update 합니다. 그리고 orphanRemoval 옵션을 true 로 하면 기존 NULL처리된 자식(= 고아 객체)을 DELETE 합니다.
일반적인 Entity였다면 orphanRemoval 옵션에 의해 정상적으로 상위 Entity에서 삭제 시 하위 엔터티 자체가 삭제되어야했으나 CertificateUsgae Entity는 m:m 관계를 관리하기 위한 테이블로써, 복합키 구성을 가지고 있었기에 recruitmentBusiness 필드를 null 값으로 구성한다하여도 pk값이 null로 취급되지 않았고, 때문에 작동하지 않은것으로 보입니다.
@Entity
@Table(name = "ceritifcate_usage")
class CertificateUsage(
certificate: Certificate,
recruitmentBusiness: RecruitmentBusiness
):BaseTimeEntity(), Persistable<String>, Serializable {
@Id
val id: String = UUID.randomUUID().toString()
@ManyToOne
@JoinColumn(name = "certificate_id")
val certificate: Certificate = certificate
@ManyToOne
@JoinColumn(name = "recruitment_business_id")
val recruitmentBusiness: RecruitmentBusiness = recruitmentBusiness
위와 같이 하위 엔터티의 PK값을 복합키에서 UUID로 변경하여 고아객체로 판단할 수 있도록 하였습니다.