728x90
반응형
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String userId;
...
}
userId를 UNIQUE 제약조건을 설정해서 중복일 때 DB 레벨에서 예외 발생하는 테스트를 해보려고 함
728x90
테스트 A (명시적 flush() 사용)
userService.join(user1);
em.flush();
assertThrows(Exception.class, () -> {
userService.join(user2);
em.flush();
});
em.flush()로 DB에 INSERT가 나가므로 UNIQUE 제약 위반이 바로 검사되어 예외가 난다.
테스트 B (flush 없음)
userService.join(user1);
assertThrows(Exception.class, () -> userService.join(user2));
그런데 테스트 B에서는 flush() 안 했는데도 예외가 난다면? 왜일까?
반응형
UNIQUE 제약 예외가 터지는 이유?
- UNIQUE 제약 예외는 DB에서 검사 → 따라서 INSERT SQL이 실제로 DB에 전송되는 시점(=flush/commit 시점)에 발생
- 그런데 언제 INSERT SQL이 DB로 전송되느냐는 상황 -> 트랜잭션 경계, 엔티티 ID 전략, JPQL 실행, Hibernate 설정 등에 따라 달라진다고 한다
- 따라서 flush()를 명시적으로 호출하지 않아도 특정 조건에서는 persist() 호출 혹은 메서드 종료 시점에 DB로 INSERT가 나가서 중복 예외가 발생할 수 있다
특정 조건중 내 상황은?
GenerationType.IDENTITY 전략에서는 엔티티를 영속화(persist)하는 시점에 데이터베이스에 즉시 INSERT 쿼리를 실행하여 기본 키(PK) 값을 받아오므로, flush() 시점이 아닌 persist() 시점에 DB와 동기화되며 PK가 할당된다고 한다
join()메서드 -> save() 호출 -> persist() 실행
바로 INSERT 쿼리를 실행하기 때문에 DB 레벨에서 예외가 발생하는 것!
반응형
'Spring' 카테고리의 다른 글
| [Spring Boot/JPA] JPA와 MongoDB 병행 시 @Transactional 설정 주의점 (멀티 트랜잭션 매니저) (1) | 2026.01.09 |
|---|---|
| [Spring/JPA] N+1과 @OneToOne LEFT JOIN (0) | 2026.01.05 |
| [Spring/JPA] Spring Boot + JPA 페이징 (0) | 2025.12.11 |
| [Spring/JPA] Entity + Lombok Builder 사용 시 컬렉션 필드 초기화 주의점 (0) | 2025.11.26 |
| [Spring/MyBatis] No constructor found in ~ matching 오류 (0) | 2025.02.10 |