JPA
JPA에서 @Entity와 Value 타입을 표현하는 Embeddable로 클래스를 매핑하려면 **기본 생성자(Default Constructor)**를 제공 해야 한다. DB에서 데이터를 읽어와 매핑된 객체를 생성할 때 기본 생성자를 사용해서 객체를 생성하기 때문이다. 이런 기술적인 제약사항으로 불변 타입의 객체에 기본 생성자를 생성해야 하는 경우가 발생한다.
기본 생성자
public class Address {
// Setter X
private String addres1;
private String addres2;
private String zipCode;
// Default Constructor
public Address(){};
public Address(String a1, String a2, String c){
address1 = a1;
address2 = a2;
zipCode = c;
};
}
Setter가 없는 불변 객체 타입의 경우, 기본 생성자를 통해서 객체가 생성되면 불완전한 객체가 탄생하게 된다. 그리고 그것을 이용해서 비즈니 로직이 실행이 된다면..! 생각만 해도 끔찍하다.
그래서 이러한 경우를 방지할 수 있는 방법이 2가지 있다. 첫 번째는 기본 생성자(Default Constructor)의 접근 제한자를 public에서 protected로 변경하는 것이다.
두 번째는 필드 접근 방식을 사용하는 것이다. JPA는 필드와 메서드의 두 가지 방식으로 매핑을 처리할 수 있다. 메서드 방식을 사용한다면 Setter/Getter가 모두 구현되어야 한다. 이렇게 되면 도메인의 의도가 사라지고 객체가 아닌 데이터 기반으로 엔티티를 구현할 가능성이 높아진다.
필드 방식을 선택하면 Setter 방식을 사용하지 않기 때문에 Setter와 기본 생성자를 정의할 필요가 없다.
@Entity
@Access(AccessType.FIELD)
public class Address {
// Setter X
private String addres1;
private String addres2;
private String zipCode;
public Address(String a1, String a2, String c){
address1 = a1;
address2 = a2;
zipCode = c;
};
}
@ElementCollection vs @OneToMany
@ElementCollection(with @CollectionTable)
Entity와 Value Object 간의 일대다 관계를 나타낸다.
값 타입의 컬렉션임을 표현한다.
DB에는 독립적인 Table을 가지고 있지만, 도메인 모델에서는 Entity 안에 Value 타입의 컬렉션으로 포함되는 Embeddable 타입과의 1:N 관계를 표현할 때 사용한다. @CollectionTable으로 매핑되는 테이블명과 Join 컬럼명을 기재한다.
특징
@OneToMany
Entity와 Entity 간의 일대다 관계를 나타낸다.
@SecondaryTabe(name = “TABLE_NAME”, pkJoinColumns = @PrimaryKeyJoinColumn(name = “PK”))
name 속성: Value Object을 저장할 테이블을 지정한다.
pkJoinColumns: Value 테이블에서 Entity 테이블로 조인할 때 사용할 컬럼을 지정한다.