티스토리 뷰
JPA의 Entity를 수정할 때 발생한 실수에 대해서 기록한다
문제상황
JPA를 사용하면 트랜잭션 범위 안에서 Entity의 데이터를 변경할 때, 데이터를 변경하는 작업 이외에 다른 메소드는 호출하지 않는다. 이는 Entity가 영속성 컨텍스트에서 제공하는 변경 감지 덕분이다. 하지만 JPA에 대한 이해가 부족하면 다음과 같은 실수가 발생할 수 있다.
Person 클래스의 name
, address
는 nullable=false로 설정 되어있다.
그리고 Person의 name을 null로 변경 했을때 나는 예외가 발생하는 것을 기대했다. 하지만 결과는 다음과 같았다.
Person의 이름은 null로 변경되었고, 예외는 발생하지 않았다.
문제분석
@Column에 대해서
Person 클래스의 name 필드에 @Column 애노테이션이 사용되었다. 각 속성에 대한 의미는 다음과 같다
- name: 테이블의 애트리뷰트 이름
- nullable: 애트리뷰트의 값으로 null 허용 여부
- length: 데이터의 길이
여기서 nullable에 집중해야한다. nullable은 DDL로 테이블의 스키마를 정의한다. 자바 클래스의 필드가 현재 null인지 여부는 확인하지 않는다. 따라서 name은 자바 애플리케이션 상에서 null이 될 수 있다.
JPA의 영속성 컨텍스트 관리
JPA를 공부 해본 사람이면 해당 그림을 자주 접했을 것이라 생각한다. 오늘 케이스에서 중요한 메소드는 바로 flush()
메소드이다. flush() 메소드를 호출하면 쓰기 지연 저장소의 SQL을 날리면서 DB와 동기화된다.
정리하면 @Column(nullable=false)
는 테이블 스키마를 정의하기 때문에 자바 클래스의 필드 값을 직접 제한할 수 없고, 트랜잭션이 commit 되기 전에는 flush()
가 호출 되지 않기 때문에 영속성 컨텍스트에 관리되고 있는 Person의 인스턴스는 name의 값으로 null을 가질 수 있다.
강제적으로 flush()
를 호출하면 예외가 발생하는 것을 볼 수 있다.
문제해결
한 트랜잭션에서 Entity의 변경된 값을 가지고 로직을 수행할 수도 있기 때문에 데이터베이스에서 예외를 발생시키기 기다리는 것은 매우 위험하다고 생각한다. 따라서 자바 애플리케이션 레벨에서 값을 검증하는 것이 좋다고 생각한다.
'JPA' 카테고리의 다른 글
[JPA] 영속성 컨텍스트 스코프와 준영속 상태 (0) | 2021.10.14 |
---|