728x90
종류
엔티티 타입
- @Entity
- PK를 가진다
- 데이터가 변해도 식별자로 계속 추적가능한 것
값 타입
- int, string...
- PK가 없다 (값 그 자체이므로...)
- 기본값 타입 (int, Integer, String...)
- 임베디드 타입 (사용자가 정의한다)
- 컬렌션 타입 (사용자가 정의한다)
1. 기본값
- int, String 등의 기본타입
- 절대 공유되어서는 안되고 복사만 가능
- immutable해야한다
2. 임베디드 타임
class Line {
@Embedded
private Sections sections;
}
@Embeddable
class Sections {
private List<Section> sections
}
- embed된 객체의 멤버만 가져와서 사용
- 그냥 엔티티의 값이다
장점
- 재사용 가능하다
- 응집도가 높아진다
- @Embeddable을 선언한 엔티티의 생명주기에 의존한다
왜 사용하는가?
- 사용 전 후의 테이블의 수는 같다
- 잘 매핑한 ORM은 테이블 수보다 클래스가 더 많다
- 특히 List를 일급 객체로 사용할 때 유용하다
@Embeddable
- embed할 엔티에 사용
@Embedded
- 부모 엔티티에 @embeddable 태그가 붙은 엔티티를 적용시 사용
- 기본 생성자 필수
@AttributeOverrides
- 한 엔티티에서 같은 값 타입을 사용할 경우
- 컬럼명이 중복될 경우
@AttributeOverride
- 구체적인 컬럼명 지정
@Embedded
@AttributeOverrides({
@AttributeOverride(name="city", column = @Column(name="HOME_CITY")),
@AttributeOverride(name="street", column = @Column(name="HOME_STREET")),
@AttributeOverride(name="zipcode", column = @Column(name="HOME_ZIPCODE"))
})
private Address homeAddress;
@Embedded
private Address workAddress;
값 타입 복사
- 값타입을 공유하는 것은 위험하다
- 대신 값타입을 복사해서 사용할 수는 있다
// 값을 복사
Address copyAddress = new Address(homeAddress.getCity(), homeAddress.getStreet(), homeAddress.getZipcode());
Customer customer2 = new Customer();
customer2.setUsername("customer2");
customer2.setHomeAddress(copyAddress);
customer2.setWorkPeriod(new Period());
em.persist(customer2);
// 첫번째 customer의 city만 newCity로 바꾸고 싶어
customer1.getHomeAddress().setCity("newCity");
값타입 컬렉션
- 데이터베이스는 기본적으로 컬렉션을 넣을 수 없다
- 1대다 매핑만 가능
- 멀티 셀렉트 할 때 사용
- 추적할 필요도 없고 값이 바껴도 업데이트 할 필요없을 때
- 웬만하면 쓰지마라... ⇒ 1대다 관계 + Cascade + orphanRemoval 쓰자...
@ElementCollection
@CollectionTable(name = "FAVORITE_THEME", joinColumns = @JoinColumn(name = "USER_ID"))
@Column(name = "FAVORITES")
private Set<String> favorites = new HashSet<>();
@ElementCollection
- Collection 자료구조에 사용되는 어노테이션
- 데이터베이스는 리스트를 컬럼으로 가질 수 없으므로 테이블을 추가 생성한다
- 부모_자식의 형식으로 임의의 테이블과 컬럼명을 자동으로 지어준다
@CollectionTable
- @ElementCollection의 테이블과 컬럼명을 지정할 수 있다
장점
- 재사용 가능
- 높은 응집도
- 값 타입만 사용하는 메소드 사용가능
- 값 타입을 소유한 엔티티의 생명주기에 의존
- 객체 지향적으로 사용 가능
- 잘 설계한 ORM 어플리케이션은 매핑한 테이블 수보다 클래스 수가 더 많다
- 현업에서 왕창 쓰는 것은 아닌데...
- 무튼 좋다 잘 사용하자
- 절대 공유되어서는 안된다! ⇒ 한군데에서만 쓰자
- 두 객체에서 공유하고 싶다면 엔티티로 만들어야 한다
- 항상 값을 복사해서 사용하면 공유 참조로 발생하는 부작용을 피할 수 있다
한계
- 값 타입은 자바의 기본타입이 아니라 객체 타입이다
- 객체의 공유 참조를 피할 수 없다
- 공유를 하지말고 복사를 하자
불변 객체!
로 만든다- 객체 타입을 수정 못하도록 부작용 전면차단
- 생성 시점 이후 값을 절대 바꾸지 않도록 변경
- 생성자로만 생성
- setter 절대 금지 등...
- 불변객체를 만드는 방법은 불변객체는 어떻게 만들까 를 참고하시기 바랍니다
- 값타입은 동일성(==) 보다는 동등성(equals) 비교
- eqauls 메소드를 적절하게 재정의 ⇒ 자동으로 만들어 주는거 써라...
- 근데 현업에서는 eqauls 비교할 일이 별로 없다...
그럼 값타입 컬렉션 언제쓸까
- 진짜 단순할때
- 멀티 셀렉트
- 메뉴 선택할 때 멀티 셀렉트할 때만
- 혹은 x, y 좌표..
- ["play","food","game"]...
- 추적할 필요도 없고 값이 바껴도 업데이트 칠 필요없을 때
- 왠만하면 엔티티사용하고 왠만하면 값타입 엔티티 쓰지마라
728x90