나는 JPA 엔티티를 만들면 항상 getter, setter을 만들었었다. 하지만 setter는 사용하지 않는 게 좋다고 한다.
이 글은 그 이유를 간단하게 기록해본 것이다.
JPA에서 데이터 타입은 크게 값 타입과 엔티티 타입으로 나뉜다.
여기서 값 타입은 기본값 타입, 임베디드 타입, 컬렉션 값 타입 으로 나뉘고 기본값 타입은 자바 기본 타입(int, double), 래퍼 클래스(Integer), String 로 나뉜다.
엔티티를 구성할 때 값 타입으로 구성하는 경우가 많은데 각 값 타입은 다른 엔티티들과 공유를 하면 위험하다. 한 엔티티에서 다른 엔테티의 값을 변경하면 위험하기 때문이다.
일반적인 자바 기본 타입은 값을 대입하면 복제가 이뤄진다. 하지만 임베디드 타입같은 객체형식의 값타입은 값을 대입하면 복제가 아닌 참조가 일어나서 대입한 값이 변하면 원래의 값도 변하게 된다. 이는 매우 위험한 상황이기 때문에 조심하야 한다.
이를 위한 해결법은 첫번째로 참조가 아닌 복사의 방식을 이용하면 된다. 하지만 이는 임시적인 방식이 뿐 객체의 공유 참조는 피할 수 없다. 즉, 근본적인 해결책이 필요한데 가장 단순한 방법은 객체의 값을 수정하지 못하게 막으면 된다. 이를 불변객체라 하는데 값 타입은 될 수 있으면 불변 객체로 설계해야 한다.
불변 객체로 설계하는 가장 간단한 방식은 생성자로만 만들고 setter를 만들지 않으면 된다.
그렇게 하면 값을 수정할 수 없으므로 공유한다 해도 문제가 발생하지 않는다.
참고로 흔히 사용되는 Interger, String 도 불변객체이다.
또 하나의 이유는 만약 setter을 무작정 사용한다면 해당 엔티티의 값들이 어제 어디서 변해야 하는지 코드상으로 명확하게 구분할 수가 없어, 차후 변경 시 복잡해질 것이다.
또 하나의 이유는 가독성 문제이다. 단순히 setter만 사용한다면 복잡한 의도에 대해서는 한번에 알아보기가 힘든 경우가 있다. 그렇기에 setter를 사용하기 보다는 update 같은 이름으로 메서드를 만들어서 외부 로직에서 호출하여 사용하는 것이 좋을 것이다. 자세한 내용은 https://bloowhale.tistory.com/97 를 참고해보길 바란다.
참고
자바 ORM 표준 JPA 프로그래밍
https://bloowhale.tistory.com/97
'JPA' 카테고리의 다른 글
JPA 두번 이상의 left join fetch가 필요할 때 해결 방법(MultipleBagFetchException 문제 해결) (0) | 2021.08.23 |
---|---|
JPA 특정 엔티티 삭제시 연관된 엔티티도 함께 삭제하기 (0) | 2021.08.15 |
JPA 임베디드 타입 (0) | 2021.07.22 |
JPA - 프록시와 연관관계(즉시로딩, 지연로딩, N + 1 문제) (0) | 2021.07.19 |
JPA 객체 매핑- 연관 관계 (0) | 2021.07.08 |