JPA 에서 final 클래스, enum, interface, inner 클래스를 엔티티 클래스로 사용할 수 없는 이유?
Intro
final 클래스를 사용할 수 없는 이유는 JPA가 프록시 객체를 사용하기 때문입니다.
JPA는 클래스를 상속 & 확장해서 프록시 객체를 생성합니다.
ex) User의 프록시 객체는 User_$$_jvst123_0 같은 이름의 하위 클래스로 생성됨
간단히 프록시 객체에 대해 알아보면
- 하위 클래스는 엔티티 클래스의 상속을 통해 프록시 객체의 동작을 구현하며, 실제 객체의 상태와 데이터를 로딩하는 데 필요한 기능을 제공
- 실제 엔티티 객체의 참조를 유지
- 프록시 객체의 메서드 호출 시 엔티티 객체의 데이터가 필요한 경우 1차 캐시에서 엔티티 객체가 존재하는지 확인
- ex) getName() → 데이터베이스에서 name 데이터 필요
- 없다면, 데이터페이스에서 데이터를 로딩 & 캐시 저장 → 실제 객체로 대체하여 메서드 실행
- Reflection API를 이용해서 프록시 객체를 생성
- 그렇기 때문에 기본 생성자 필수 (엔티티 클래스)
- 프록시 객체의 필드들을 초기화 하기 위해 setter 사용
이 밖에 기본적으로 테이블과의 매핑에 적합하지 않거나 제약사항을 가지고 있습니다.
Final 클래스
위의 특징을 가지기 때문에, Final 클래스는 사용할 수 없습니다.
- Final 클래스는 상속이 되지않음으로 프록시를 생성하는 기능을 사용할 수 없습니다.
Enum
열거형 상수를 정의하기 위한 클래스이기 때문에 테이블과 매핑되는 데이터를 표현하기에 적합하지 않습니다.
- 엔티티 클래스는 애플리케이션 사용간 지속적으로 다른 값을 가진 데이터 상태를 나타내고, 수정 (가변 상태) 또한 될 수 있기 때문에 상수가 정의되어 있는 Enum 은 적합하지 않다고 생각합니다.
Interface
인터페이스는 일반적으로 인스턴스화 할 수 없고, 테이블과 직접적으로 매핑되지 않습니다.
- 메서드를 오버라이딩하면서 익명 객체로 객체를 만드는 경우 제외
Inner 클래스
클래스 내 중첩된 클래스인 내부 클래스는 외부 클래스의 인스턴스에 종속되어있는 구조입니다.
엔티티 클래스는 독립적으로 관리하고 매핑하는 것을 선호하며 따라서 Inner 클래스는 적합하지 않습니다.
더 알아볼것
- Reflection API
- 불변객체와 final 클래스는 직접적인 관련이 없다.
- 클래스의 final 키워드는 상속 금지 방지
- final 필드 : 초기화된 후 다른 값 변경 불가 (컴파일 오류)
- final 메서드 : 하위 클래스에서 오버라이딩 불가능 (최종 구현)
- 불변 객체는 한 번 생성되면 내부 상태가 변경되지 않는 객체
- 조건 : 모든 필드 final, 클래스 내부 상태변경 메서드x (ex setter)
- 가장 작은 필드까지 객체로 만들어 불변객체로 구현하는 방법
Leave a comment