JPA 값 타입 이란?
들어가며
값 타입은 기본적으로 3가지로 나눌수있다.
- 기본값 타입
- 자바 기본타입( int ,double)
- 래퍼 클래스(Integer)
- String
- 임데디드타입
- 컬렉션 값 타입
기본값 타입은 기본적으로 자바에서 제공하는 타입이다. 임베디드 타입은 JPA에서 직접 정의한 값 타입이다.
컬렉션 타입은 하나이상 값 타입을 저장할때 사용된다.
※ Lombok을 사용하여 작성함
기본값 타입
기본값 타입은 Entity 클래스를 만들때 기본으로 만들때 사용하는 타입이다.
@Entity
@Data
public class Member {
@Id
private Long id; // 기본값 타입
private String username; // 기본값 타입
}
임베디드 값 타입
임베디드 값타입은 사용자가 직접 정의해서 사용하는 타입을 JPA에서는 임베디드 값 타입이라고 부른다.
예를 들어 생각해보자 회원가입을 구현한다고 생각해보면 사용자의 정보등을 기업하는 엔티티를 만들어야한다. 그중에 주소를 생각해보자
@Entity
@Data
public class Member {
...
private String zipcode;
private String address;
private String detailAddr;
private String subAddr;
}
Member 객체는 우편번호와 주소등을 가진다. 라고 볼수있다. 하지만 이렇게 설명하는것보다는 Member객체는 주소를 가지고있다라고 설명하는게더 좋은 방법이다. 그래서 여기서 임베디드 값 타임을 사용하여 코드를 수정하면
Member
@Entity
@Data
public class Member {
...
@Embedded Address address;
}
Address
@Embeddable
@Data
public class Address {
private String zipcode;
private String address;
private String detailAddr;
private String subAddr;
}
간단하게 사용할수있다. 여기서 임베디드를 정의한 클래스에는 @Embeddable 정의해주고 사용할 클래스에서는 @Embedded 를 사용해서 적용할수있다.
여기서 직장 Address임베디드 값 타입 가지고 직장 주소도 추가한다고 하면
@Entity
@Data
public class Member {
...
@Embedded Address address;
@Embedded Address companyAddress;
}
이런식으로 작성해서 사용할것이다. 하지만 중복으로 값이 적용되서 오류가 발생할수있다 그때는 @AttributeOverride 애노테이션을 사용해 재정의 할수있다.
@AttributeOverride 재정의
@AttributeOverrides({
@AttributeOverride(name = "zipcode", column = @Column(name = "company_zipcode")),
@AttributeOverride(name = "address", column = @Column(name = "company_address")),
@AttributeOverride(name = "detailAddr", column = @Column(name = "company_detailAddr")),
@AttributeOverride(name = "subAddr", column = @Column(name = "company_subAddr"))
})
@Embedded Address companyAddress;
재정의 해서 사용할수있다
임베디드타입이 null이면 매핑한 컬럼 값은 모두 null이 된다.
값 타입과 불변객체
값 타입 공유 참고
앞서 설명한 Address 타입을 공유해서 사용하면 위험하다. 왜냐하면 임베디드 타입은 하나인데 여러곳에서 수정하고 조회하면 마지막으로 수정된 값이 적용되 조회되기때문에 예상치 못한 부작용이 발생하게된다.
이런한 부작용을 막기위해서는 값 타입을 복사하거나, 불변객체로 만들어 사용하면된다.
값 타입 복사
member.setAddress(new Address());
Address address = member.getAddress();
Address newAddress = address.clone();
newAddress.setZipcode("city");
이런식으로 clone() 메소드를 사용해여 객체를 복사본을 만들어 사용하면된다.
불변 객체
객체를 불변하게 마들면 값을 수정할수 없으므로 부작용을 막을수있다. 따라서 값타임은 불변 객체로 설계해야한다.
불변객체로 만들기 위해서는 수정제 메소드를 제저하거 생성자를 통해서 값을 설정하게 하면된다.
@Embeddable
@Getter
public class Address {
private String zipcode;
private String address;
private String detailAddr;
private String subAddr;
public Address() {} //기본 생성자 필수
public Address(String zipcode, String address, String detailAddr, String subAddr) {
this.zipcode = zipcode;
this.address = address;
this.detailAddr = detailAddr;
this.subAddr = subAddr;
}
}
이렇게 불변객체로 만들게되면 값을 설정하려면 생성자를 만들어 수정해야하며 수정자를 통해서는 변경할수가 없다.
값타입 비교
타입을 비교하기 위해서 자바에서는 2가지가있다.
- 동일성 비교 : 인스턴스의 참조 값을 비교, == 사용
- 동등성 비교 : 인스턴스의 값을 비교, equals() 사용
Address address1 = new Address("zipcode", "address", "detailAddr", "subAddr");
Address address2 = new Address("zipcode", "address", "detailAddr", "subAddr");
address1값과 address2 값을 동일성 비교를 하게되면 false 로 나오게될것이다. 생성자를 통해서 2개를 만들었기때문에 인스터스 값이 달르기때문이다. 원하는 값을 얻기 위해서는 동등성 비교 (address1.equals(address2))를 통해서 값을 비교해야 원하는 값을 얻을수있다.
값 타입 컬렉션
JPA에서 켈렌션 형태로 값을 관리하는 방법이다.
예를 들어 주문 엔티티가 있을때 주문에 속한 여러 상품을 리스트 형태로 관리하는 것을 생각해보자
Order
@Entity
@Data
public class Order {
@Id
private Long id;
@ElementCollection
@CollectionTable(name = "order_items", joinColumns = @JoinColumn(name = "order_id"))
private List<OrderItem> items = new ArrayList<>();
}
- Order 엔티티는 OrderItem 타입의 리스트를 갖는다.
- @ElementCollection : 컬렉션을 정의하는데 사용된다.
- @CollectionTable : 컬렉션을 저장할 테이블을 지정한다.
OrderItem
@Embeddable
@Data
public class OrderItem {
private String productName;
private int quantity;
}
이런식으로 컬렉션 형태로 만들어서 사용할수있다. 하지만 이러한 방식에는 제약사항이 발생한다.
제약사항
컬렉션의 100번째 관련 리스트를 수정하려면 100번째 연관된 정보를 모두 지우고 새로운 값을 다시 지정해줘야하는 제약사항이 발생하게된다 그래서 일대다 , 다대일 같이 매핑전력을 사용해서 사용하는것이 더좋은 방법일수도있다.
참고
'JPA' 카테고리의 다른 글
[JPA] QueryDSL 에서 FROM절에 SubQuery 및 ROW_NUMBER() 사용 방법 (1) | 2024.09.18 |
---|---|
[JPA] QueryDsl 를 이용한 무한 페이징(Infinite scrolling) - 성능 개선 (0) | 2024.05.02 |
[JPA] OSIV (1) | 2024.01.08 |
[JPA] 프록시와 연관관계 관리 (0) | 2024.01.05 |