
@Inheritance와 관련된 테이블 상속 처리 방식에 대한 설명과 함께, 예제 코드 및 좀 더 구체적인 분석을 통해 해당 문제를 해결하는 과정과 그 원인을 더욱 명확히 이해할 수 있도록 보완할 수 있습니다.
문제는 @Inheritance(strategy = InheritanceType.JOINED)를 사용한 상속 관계에서 발생한 것입니다.
이를 통해 두 개의 테이블(부모 테이블 Account와 자식 테이블 SuperAccount)이 생성되고, 한쪽 테이블에서 다른 테이블을 참조하면서 데이터 삭제 시 문제가 발생한 것입니다.
@Inheritance(strategy = InheritanceType.JOINED) 방식에서는 부모 클래스 Account 테이블과 자식 클래스 SuperAccount, NormalAccount 테이블이 각각 별도로 생성됩니다.
이 구조에서는 부모 테이블(Account)에서 자식 테이블을 참조하고, 자식 테이블에서는 부모 테이블의 ID를 외래키로 참조합니다.
이로 인해 삭제 또는 수정이 두 테이블에 영향을 미칠 수 있는데, 만약 자식 테이블에서 존재하지 않는 데이터를 참조하는 상황이 발생하면, OptimisticLockingFailureException과 같은 예외가 발생할 수 있습니다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public class Account {
@Id
private Long id;
private String name;
}
@Entity
@DiscriminatorValue("sa")
public class SuperAccount extends Account {
private String superAccountField;
}
@Entity
@DiscriminatorValue("na")
public class NormalAccount extends Account {
private String normalAccountField;
}
1. 상속 관계에 의한 테이블 생성: Account는 부모 테이블이고, SuperAccount, NormalAccount는 자식 테이블입니다.
부모 테이블은 공통 필드를 관리하고, 자식 테이블은 type 컬럼을 기준으로 구분됩니다.
2. 데이터 삽입: 데이터 생성 시 NormalAccount로 삽입하였지만, 나중에 수동으로 type 컬럼을 'na'에서 'sa'로 변경했습니다.
3. 삭제 시 예외 발생: delete를 수행할 때, SuperAccount 테이블에서 해당 id를 찾을 수 없어서 OptimisticLockingFailureException 예외가 발생했습니다.
// 정상적으로 삭제가 될 경우
AccountRepository.delete(superAccount);
최종적으로 문제를 해결한 방법은 데이터를 삭제할 때, Account 테이블에서 SuperAccount 또는 NormalAccount로 변환된 데이터의 type 컬럼을 일관되게 처리하여, 삭제할 때 실제로 존재하는 데이터를 삭제할 수 있도록 했습니다.