티스토리 뷰

spring boot 버전을 올리면서 3.4.x 버전을 사용하게 됐고, 동작을 확인하던 도중 기존 코드에서 에러가 발생했다.

Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

해당 로우가 다른 트랜잭션에서 업데이트되거나 삭제되었다는 메시지인데, 버전을 올리지 않으면 해당 에러는 발생하지 않았다.

 

해당 문제가 발생할 수 있는 상황은 이렇다.

// 엔티티 정의
@Entity
@Table(name = "person")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Person {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "person_id")
    private Long id;

    @Column(name = "person_name")
    private String name;
}

// 문제가 발생하는 테스트 코드
@Test                                                
void id를_할당한채로_저장시도() {                              
    Person person = new Person(100L, "LichKing");
    personRepository.save(person); // hibernate 6.6.0 부터 예외 발생                   
}                                                    

@Test                                                      
void 엔티티_제거_후_재저장() {                                      
    Person person = new Person(null, "LichKing");          
    Person saved = personRepository.save(person);          
    personRepository.delete(saved);                        
    personRepository.save(person); // hibernate 6.6.0 부터 예외 발생                   
}

저장하려는 엔티티에 id 가 할당되어 있으면 spring data jpa 는 EntityManager 의 persist 가 아닌 merge 를 호출하게 된다. merge 가 호출되면 그때부턴 hibernate 의 영역인데, 할당된 id 에 해당하는 로우가 있으면 update 를 실행하고 없으면 insert 를 실행한다. 이때 id 생성을 DB 에 위임하고 있다면(쉽게 얘기해서 @GeneratedValue 애노테이션이 달려있다면) 실제 전달된 id 를 사용하지 않고, DB 에서 정해주는 id 로 엔티티를 저장한다.

 

즉 id 를 100으로 할당해서 저장을 했을때 auto increment 로 id 가 60을 가져야하는 상황이라면 100은 버리고 60으로 저장된다는 의미이다. 이게 옳으냐마냐의 고민과는 별개로 hibernate 6.5.x 까지는 이렇게 동작했다.

 

생각해보건대 특별한 이유가 있지 않은 이상 존재하지 않는 id에 대해서 저장을 하는 경우는 없을 것이기에 웬만하면 이 변경을 눈치채지 못하고 그냥 넘어갈 것 같다. 하지만 혹시라도 버전을 올리면서 위 에러를 만난다면 알게모르게 어디선가 id를 갖고있는 상태로 저장을 하는건 아닌지 찾아서 수정하자.

 

해당 변경은 hibnernate 6.6.0 부터 반영되었으며, spring boot 기준 3.4.0 부터 hibernate 6.6.x 을 사용한다.

 

참고자료

https://docs.jboss.org/hibernate/orm/6.6/migration-guide/migration-guide.html#merge-versioned-deleted

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함