이 포스팅 시리즈는 인프런에서 김영한님의 JPA활용 강의를 듣고서
궁금한 점과 중요하다고 생각하는 부분을 정리한 것입니다.
내가 모르는 어노테이션들이 있길래 찾아보았다
하위 클래스에 선언한다. 엔티티를 저장할 때 슈퍼타입의 구분 컬럼에 저장할 값을 지정한다. 어노테이션을 선언하지 않을 경우 기본값으로 클래스 이름이 들어간다.
주소같이 여러개로 나뉘어진 필드는 회원 엔티티의 필드에 각각 사용하기에
상당히 불편하다.
private String city;
private String street;
private String zipcode;
얘네를 엔티티에 전부 넣겠다고?
이럴 때 포현할 객체를 하나의 컬럼에 넣기 위해 @Embedded
, @Embeddable
어노테이션을 사용한다.
우선 주소를 하나로 표현할 클래스와 필드를 생성하고, 클래스 위에 @Embeddable
(생략가능)을 쓴다.
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Address {
private String city;
private String street;
private String zipcode;
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
}
위에서 만든 객체 필드를 엔티티에 생성하고 위에 @Embedded
를 붙여주면 끝난다.
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@Embedded
private Address address;
엔티티에 Enum 클래스를 매핑할 때는 반드시
@Enumerated(EnumType.STRING)
어노테이션을 사용해야 한다.
Enum값이 DB에 저장될 때는 0,1과 같은 숫자가 들어간다. 하지만 Enum 클래스에 새로운 상수가 선언될 시에 숫자의 순서가 꼬여버리게 된다.
그러니 반드시 Enum은 String값으로 저장되게 해야 한다.
@Setter를 사용한다면 변수가 바뀔 경우의 수가 매우 많아지게 된다.
즉, 어디에서 값이 바뀌는지 파악이 어려워지고, 특히 많은 연관관계를 맺은 엔티티는 setter로 인해 안정성이 떨어진다. 그러니 엔티티에서는 setter 대신 생성자로 초기화 해서 값 변경을 불가능하게 해야한다.
JPA 스펙상 엔티티나 임베디드 타입( @Embeddable )은 자바 기본 생성자(default constructor)를 public 또는 protected 로 설정해야 한다. JPA 구현 라이브러리가 객체를 생성할 때 리플렉션 (구체적인 클래스 타입을 알지 못해도, 그 클래스의 메소드, 타입 변수들에 접근할 수 있도록 해주는 API
) 같은 기술을 사용할 수 있도록 지원해야 하기 때문이다.
public 으로 두는 것 보다는 protected 로 설정하는 것이 그나마 더 안전하다.
protected 클래스명() {
}
또는
@NoArgsConstructor(access = AccessLevel.PROTECTED)
JPA에서 데이터를 조회할 때는 즉시로딩(EAGER)과 지연로딩(LAZY)가 있다.
예를 들어 member 엔티티와 Team 엔티티가 N:1 매핑이 되어있을 때,
즉시로딩은 member를 조회할 때 member가 참조한 Team 까지 조회하는 쿼리를 날린다. 즉, 한꺼번에 데이터를 불러온다. member를 조회할 때 사용하지 않는 Team도 조회하게 되므로, DB의 성능이 떨어지게 된다.
지연로딩은 member를 조회할 때는 Team을 조회하지 않고, 실제로 Team을 사용하는 시점에 조회 쿼리가 나간다.
그렇기 때문에 보통은 지연로딩을 사용하는 게 바람직하다.
CASCADE는 영속성 전이라고도 하며, 특정 엔티티와 연관 엔티티를 함께 영속 상태로 만들고 싶을 때 사용한다.
ex)) 부모 저장시 자식도 저장, 부모 삭제시 자식도 삭제
예제:
@OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE)
private List<Order> orderList;
https://ict-nroo.tistory.com/128
https://galid1.tistory.com/592
글에서 잘못된 점이나 궁금한 점은 댓글로 남겨주세요🧐