@GeneratedValue(strategy = GenerationType.IDENTITY)
기본키 생성을 데이터베이스에게 위임하는 방식이다. ID값을 따로 할당하지 않아도 데이터베이스가 자동으로 AUTO_INCREMENT로 설정한다.
@GeneratedValue(strategy = GenerationType.SEQUNCE)
데이터베이스의 Sequence Object를 사용하여 데이터베잇가 자동으로 기본키를 생성해준다.
클래스에 아래와 같은 어노테이션이 필요하다.
@SequenceGenerator(
name = "USER_NAME",
sequenceName = "USER_SEQUENCENAME",
initailValue = 1,
allocationSize = 50
)
@GeneratedValue(strategy = GenerationType.TABLE)
키를 생성하는 테이블을 사용하는 방법으로 Sequnce와 유사하다.
아래와 같이 클래스에 어노테이션이 필요하다.
@TableGenerator(
name = "USER_NAME",
table = "USER_TABLE",
pkColumnValue = "USER_VALUE",
allocationSize = 1
)
@GeneratedValue(strategy = GenerationType.AUTO)
기본 설정 값으로 각 데이터베이스에 따라 기본키를 자동으로 생성한다.
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@Embedded
private Address address;
}
예를들어 위와같이 Address 정보를 하나의 Class로 담지 않는다면 직접 Address 정보를 하나의 변수로 만들어주어야한다. 하지만 Address 클래스를 만들어 객체로 표현하게되면 보다 객체지향적인 코드가 될것이다.
@Embeddable
@Getter
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로 표현하고 내장 타입을 @Embeddable로 설정해 표현해야한다. 하이버네이트에서 컴포넌트를 임베디드 타입이라고하며, 임베디드 타입은 기본 생성자가 필수이다.
이건 양쪽방향에 다 적어줘야함.
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
@NotEmpty
private String name;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
@Entity
@Table(name="orders")
@Getter @Setter
public class Order {
@Id @GeneratedValue
@Column(name="order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="delivery_id")
private Delivery delivery;
private LocalDateTime orderDate; //주문시간
@Enumerated(EnumType.STRING)
private OrderStatus status; //주문상태 [ORDER, CANCEL]
}
현재 Order와 Member 두 클래스를 확인해보면 Order은 Member를, Member는 Order을 가지고있는 양방향관계이다.
Order에만 member_id가 외래키로 존재하고, 하나의 값이 바뀌면 외래키가 변경될 수 있도록 설정해 주어야한다. 이때 연관관계 주인이 필요하다.
Order 테이블에 외래키가 있기때문에 Order테이블에 존재하는 member를 연관관계 주인으로 잡는게 좋다.
연관관계 거울(연관관계 주인이 아닌 반대방향) 일 경우 @OneToMany(mappedBy = "{누구에의해서?!}")로 써야한다. 그럼 이제 여긴 읽기 전용으로 열리게된다.
이렇게 설정하게되면, Member 엔티티에 있는 orders는 양방향 관계임을 나타내고, Order 엔티티에 있는 member를 맵핑하게된다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "ENTITY_TYPE")
public abstract class BaseEntity {
@Id
@GeneratedValue
private Long id;
}
@Entity
@DiscriminatorValue("A")
public class EntityA extends BaseEntity {
private String propertyA;
}
@Entity
@DiscriminatorValue("B")
public class EntityB extends BaseEntity {
private String propertyB;
}
@DiscriminatorColumn 어노테이션은 "ENTITY_TYPE"이라는 구분 열을 정의한다. 그리고 각 서브 엔티티(EntityA와 EntityB)는 @DiscriminatorValue 어노테이션을 사용하여 구분 열의 값을 지정하여 서브 엔티티를 식별한다.
이렇게 하면 데이터베이스 테이블에는 하나의 테이블만 있지만, 각 엔티티는 구분 열의 값을 통해 구별된다.
레퍼런스
https://velog.io/@gudnr1451/GeneratedValue-%EC%A0%95%EB%A6%AC
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발(인프런_김영한)