[Spring boot] JPA 어노테이션(1)

90000e·2023년 11월 8일
0

[Spring]

목록 보기
5/8
post-thumbnail

@Entity

  • 태이블과의 매핑
  • @Entity가 붙은 클래스는 JPA가 관리하게된다.

@Id

  • 기본키 매핑

@Table(name="")

  • DB에 저장될 테이블의 이름 설정
  • 설정하지 않으면 클래스의 이름으로 설정된다.

@GenerateValue

  • 기본키 생성전략
  • 직접할당, 자동할당으로 나뉨.

IDENTITY 방법

@GeneratedValue(strategy = GenerationType.IDENTITY)

기본키 생성을 데이터베이스에게 위임하는 방식이다. ID값을 따로 할당하지 않아도 데이터베이스가 자동으로 AUTO_INCREMENT로 설정한다.

SEQUNCE 방법

@GeneratedValue(strategy = GenerationType.SEQUNCE)

데이터베이스의 Sequence Object를 사용하여 데이터베잇가 자동으로 기본키를 생성해준다.
클래스에 아래와 같은 어노테이션이 필요하다.

 @SequenceGenerator(
    	name = "USER_NAME",
        sequenceName = "USER_SEQUENCENAME",
        initailValue = 1,
        allocationSize = 50
        )

TABLE 방법

@GeneratedValue(strategy = GenerationType.TABLE)

키를 생성하는 테이블을 사용하는 방법으로 Sequnce와 유사하다.
아래와 같이 클래스에 어노테이션이 필요하다.

 @TableGenerator(
    	name = "USER_NAME",
        table = "USER_TABLE",
        pkColumnValue = "USER_VALUE",
        allocationSize = 1
        )

AUTO 방법

@GeneratedValue(strategy = GenerationType.AUTO)

기본 설정 값으로 각 데이터베이스에 따라 기본키를 자동으로 생성한다.

@Column(name="")

  • DB에 저장될 컬럼의 이름 설정. 설정하지 않으면 이름으로 설정된다.

@Embeddable

  • 어딘가 내장 될 수 있다는 표시 (내장타입). 이건 변수나 클래스에만 작성하면 되지만 둘다 작성해주는게 일반적인 방법이다.
@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로 설정해 표현해야한다. 하이버네이트에서 컴포넌트를 임베디드 타입이라고하며, 임베디드 타입은 기본 생성자가 필수이다.

@ManyToOne

  • 다대일 관계

@OneToMany

  • 일대다 관계

이건 양쪽방향에 다 적어줘야함.

@JoinColumn(name="")

  • 뭘로 맵핑해줄껀지 설정. FK에 사용. 연관관계 주인에게 써주는듯.
  • 일대다 관계일때 사용하는 어노테이션
@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를 맵핑하게된다.

@Inheritance(strategy = ~~)

  • @Inheritance(strategy=Joined) : 가장 정교화된 스타일
  • @Inheritance(strategy=SingleTable) : 한테이블에 다때려박는거
  • @Inheritance(strategy=TablePerClass) : 테이블을 나누는 것

@DiscriminatorColumn(name = ""), @DiscriminatorValue("")

  • SingleTable에서 클래스를 구분하는 방법이다.
@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 어노테이션을 사용하여 구분 열의 값을 지정하여 서브 엔티티를 식별한다.

이렇게 하면 데이터베이스 테이블에는 하나의 테이블만 있지만, 각 엔티티는 구분 열의 값을 통해 구별된다.

@Enumerated(EnumType.~~)

  • ORDINAL : 디폴트 1,2,3,4 숫자로들어감 이거 중간에 수정되면 혼란이 생긴다.
  • STRING : 위의 단점으로 인해 STRING으로 써야한다. 중간에 수정되서 순서밀려도 상관이 없다.

레퍼런스
https://velog.io/@gudnr1451/GeneratedValue-%EC%A0%95%EB%A6%AC
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발(인프런_김영한)

profile
내가 복습하려고 쓰는 블로그

0개의 댓글