본문 바로가기
개발/Java

[JPA] Jakarta Spec(JSR 338) - (1)Entity, Field, Access Type

by Mingvel 2023. 8. 17.

Jakarta EE 로고

SpringBoot 3.x 버전과 호환되는 SpringBoot starter-data-jpa 패키지에는 

 

jakarta.persistence-api:3.1.0 라이브러리가 포함되어 있다

 

jakarta.persistence-api 라이브러리는 Java Application 개발자가 관계형 데이터베이스를 관리하기 위해

 

Java 도메인 모델을 사용하는 객체/관계형 매핑 기능을 제공한다

 

starter-data-jpa 를 사용하는 개발자에겐 익숙한

 

@Entity, @Table, @Id, @Enumerated 와 같은 어노테이션은 모두 jakarta.persistence-api 라이브러리에서 제공하고 있다

 

그렇다면, JPA를 잘 이해하고 싶다면 SpringBoot의 기본 제공 라이브러리인 jakarta.persistence-api 라이브러리를 열심히 공부해야 할까?

 

필자의 의견은 Yes 이다

 

이 부분에는 합리적인 궁금증이 생길 수 있다

 

Jakarta의 Persistence API는 JSR 338 스펙의 구현체인데 JPA를 알고 싶으면 JSR 338 스펙을 보는 게 맞지 않나요?

 

JSR 338Java Community Process (JCP)를 통해 정의된 Java Persistence API (JPA) 의 명세이다.

 

반면에 Jakarta PersistenceEclipse Foundation에서 주도하고 있는 Jakarta EE 프로젝트의 일부로,

 

기존의 JPA를 기반으로 한 데이터 영속성 스펙이다

 

Oracle과 Eclipse Foundation 사이의 라이선스 및 상표권 문제로 인해 Java EE가 Eclipse Foundation으로 이전되면서 'Jakarta EE'로 이름이 바뀌게 되었고,

 

이 과정에서 기존의 Java EE 명세의 내용을 계승하면서 몇몇 부분에서 이름만 변경되어야 했기 때문에

 

원래의 JPA와 Jakarta Persistence 사이에 큰 차이점이 없다

 

실제로 JSR 338 스펙Jakarta Persistence 스펙을 비교해보면 상당 부분 동일한 것을 확인할 수 있다

 

이는 Jakarta Persistence가 기존의 JPA 스펙을 계승하고 있고

 

JPA는 이미 오랜 기간 동안 사용되어 오면서 검증된 기술이기에 큰 변화 없이 안정적인 기술로 유지하려는 의도가 있을 수 있다

 

위와 같은 이유로 필자는 JSR 338 스펙보단 Jakarta Persistence 스펙을 보는 것을 더 권장한다

 

본론으로 들어가서 이번 시간에는 Jakarta Persistence 스펙에 명시 된 Entity 클래스와, Entity 클래스에 포함 된 인스턴스 변수, 및 접근 유형(Access Type) 에 대해 검토해보고자 한다

 


Entity Class

 

  • Entity 클래스는 반드시 @Entity 어노테이션이 붙어 있거나, XML descriptor에 entity로 명시되어 있어야 한다
  • Entity 클래스는 public 혹은 protected 로 선언 된 인자 없는 생성자가 반드시 존재해야 한다 (필요에 의해 다른 생성자도 가질 수 있다)
  • Entity 클래스는 최상위 클래스(top-level class)여야 한다
  • Entity 클래스는 인터페이스 혹은 열거형으로 정의해서는 안된다
  • Entity 클래스와 포함하는 메서드, 인스턴스 변수들은 final 로 선언할 수 없다
  • Entity 인스턴스를 분리된 객체로 값을 전달하려면, Entity 클래스가 Serializable 인터페이스를 구현해야 한다
  • Entity는 상속, 연관관계, 다형성 쿼리를 지원한다
  • 추상 클래스와, concrete 클래스는 모두 Entity가 될 수 있다
  • Entity 클래스는 Non-Entity 클래스를 확장할 수 있으며, 반대의 경우도 가능하다
  • Entity 클래스의 인스턴스 변수들은 외부에서 직접 접근해서는 안된다. (getter/setter 와 같은 메서드로 사용자에게 제공해야 한다)

 

 

Entity 클래스의 인스턴스 변수

  • Entity 클래스의 인스턴스 변수는 사용 여부와 관계 없이 private, protected 혹은 package visibility 해야 한다
  • Entity 클래스의 인스턴스 변수에 접근하는 메서드는 public 혹은 protected 접근 제어자를 가져야 한다
  • Entity 클래스의 인스턴스 변수에 접근하는 메서드는 JavaBeans 읽기/쓰기 속성에 대한 메서드 네이밍 규칙을 따라야 한다
  • 컬렉션 값을 가지는 영속 필드는 Collection, Set, List, Map 인터페이스 중 하나로 정의해야 한다
    • 해당 필드에 대한 접근 또한 인터페이스 유형을 통해 이루어져야 한다
  • 컬렉션 값을 가지는 영속 필드의 메서드 시그니처는 T 형태여야 한다. ex) List<Order>
  • Entity 클래스의 인스턴스 변수에 접근하는 메서드에는 유효성 검증과 같은 비즈니스 로직이 포함되어도 괜찮다
  • 위와 같이 메서드에 비즈니스 로직이 포함되는 경우, 호출 순서에 의존해서는 안된다. (persistence provider는 로드하거나 저장할 때, 메서드 호출 순서를 정의하지 않는다)
  • Fetch Type이 Lazy로 설정 된 필드에 접근하는 경우, 영속성 컨텍스트에 해당 데이터가 load 되기 전에 직접 접근하지 않아야 한다
  • 영속성 컨텍스트가 트랜잭션에 Join 된 경우 접근 메서드에서 발생하는 runtime exception은 transaction rollback 대상으로 표시된다
  • Entity 서브 클래스는 속성에 접근하는 메서드를 재정의 할 수 있지만, 속성에 적용되는 객체, 관계형 매핑 메타데이터를 재정의 해서는 안된다
  • Entity 클래스에 정의 가능한 필드 속성 유형
    • Java primitive types
    • String
    • 직렬화 가능한 Wrapper Type
      • BigInteger
      • BigDecimal
      • Date
      • Calender
      • Date
      • Time
      • Timestamp
      • byte[]
      • Byte[]
      • char[]
      • Charater[]
      • LocalDateTime
      • LocalDate
      • LocalTime
      • OffsetTime
      • OffsetDateTime
    • 열거형(Enum) 타입
    • Entity 타입
    • Entity 컬렉션 타입
    • Embeddable 클래스
    • Embeddable 클래스 컬랙션 타입

 

 

접근 유형 (Access Type)

  • field-based 접근, property-based 접근 이 두 가지 유형을 기본적으로 제공한다
  • field-based 접근
    • 엔티티의 직접적인 필드에 접근하여 데이터를 읽거나 쓰는 방식
  • property-based 접근
    • getter와 setter 메서드를 통해 데이터에 접근하는 방식
  • 두 방식 중 한가지 방식을 채택할 경우, 엔티티 내에서 일관성을 유지해야한다 (혼용해서는 안된다)
  • Embeddable 클래스의 Access Type은 매핑 된 상위 클래스(@Embedded 를 명시한 클래스)의 Access Type에 의해 결정 된다
    • Access 어노테이션을 통해 다른 Access Type을 지정할 수 있다

 

 


 

Jakarta Spec 문서에서 다루고 있는 정의가 다양하고 깊어, 해당 내용은 게시물 한개로 다루기엔 무리가 있다고 판단하여

 

시리즈 게시물로 작성하기로 결정했습니다

반응형

댓글