kwonslog / how-to-use-jpa

0 stars 0 forks source link

JPA 표준 어노테이션 정리 #10

Closed kwonslog closed 1 month ago

kwonslog commented 5 months ago

@Entity

@Table

## @Id
- 특정 필드를 엔티티의 주 키(primary key)로 지정한다.

## @Enumerated
- Java의 열거형(enum) 타입을 데이터베이스에 매핑할 때 사용한다.
- 옵션
  - `EnumType.STRING`: 열거형의 이름을 문자열로 데이터베이스에 저장한다.
  - `EnumType.ORDINAL`: 기본값으로, 열거형의 순서(ordinal)를 데이터베이스에 저장한다. 하지만 STRING 타입을 사용하자.
    (중간에 새로운 아이템이 추가될경우 이미 저장된 순서에 영향을 주어 버그가 발생 할 수 있다.)

## @GeneratedValue
- 주 키 필드의 값을 자동으로 생성할 때 사용한다.
- 옵션
  - `strategy` : 주 키를 생성하는 방법을 지정한다.
    - `GenerationType.AUTO` : (기본값) 특정 데이터베이스에 맞게 자동으로 결정.
    - `GenerationType.IDENTITY` : 데이터베이스의 ID 자동생성 기능 사용.
    - `GenerationType.SEQUENCE` : 데이터베이스의 시퀀스를 사용.
    - `GenerationType.TABLE` : 별도의 테이블을 이요하여 주키를 관리.
  - `generator` : strategy가 SEQUENCE 또는 TABLE일 때 사용되는, 시퀀스 또는 테이블 제너레이터의 이름을 지정한다.

## @Column
-  엔티티 클래스의 필드나 프로퍼티를 데이터베이스 테이블의 컬럼과 매핑할 때 사용한다.
- 옵션
  - `name` : 기본값은 필드명이고 테이블의 컬럼명을 지정 할 수 있다.
  - `nullable` : null 값을 허용할지 여부를 지정
  - `insertable` : 엔티티가 영속화될 때 이 필드가 포함될지를 결정. 기본값 true
  - `updatable` : 엔티티가 업데이트될 때 이 필드가 포함될지를 결정. 기본값 true
``` java
@Entity
public class ExampleEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "example_column", nullable = false, length = 100)
    private String exampleField;

    // 기타 필드 및 메소드
}

@OneToOne / @OneToMany / @ManyToOne / @ManyToMany

어노테이션 옵션 설명
@OneToOne cascade 연관된 엔티티에 대한 영속성 관리 전략 지정
fetch 연관된 엔티티를 가져오는 방식 지정
optional 관계가 선택적인지 여부 지정
mappedBy 양방향 관계에서 소유가 아닌 쪽에서 사용
orphanRemoval 고아 객체 제거 여부 지정
@OneToMany cascade 연관된 엔티티에 대한 영속성 관리 전략 지정
fetch 연관된 엔티티를 가져오는 방식 지정
mappedBy 양방향 관계에서 소유가 아닌 쪽에서 사용
orphanRemoval 고아 객체 제거 여부 지정
@ManyToOne cascade 연관된 엔티티에 대한 영속성 관리 전략 지정
fetch 연관된 엔티티를 가져오는 방식 지정
optional 관계가 선택적인지 여부 지정
@ManyToMany cascade 연관된 엔티티에 대한 영속성 관리 전략 지정
fetch 연관된 엔티티를 가져오는 방식 지정
mappedBy 양방향 관계에서 소유가 아닌 쪽에서 사용

@Embeddable / @Embedded

- 추가로 @AttributeOverrides 어노테이션을 사용하여 매핑 정보를 변경 할 수도 있다.
``` java
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "street", column = @Column(name = "home_street")),
        @AttributeOverride(name = "city", column = @Column(name = "home_city")),
        @AttributeOverride(name = "zipcode", column = @Column(name = "home_zipcode"))
    })
    private Address homeAddress;

    // 생성자, Getter 및 Setter 메서드들...
}

@SecondaryTable

@Entity @Table(name = "employee") @SecondaryTable(name = "employee_contact", pkJoinColumns = @PrimaryKeyJoinColumn(name = "employee_id")) public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@Column(table = "employee_contact")
private String phone;

@Column(table = "employee_contact")
private String email;

// 생성자, Getter 및 Setter 메서드들...

}


-- employee 테이블 생성 CREATE TABLE employee ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL );

-- employee_contact 테이블 생성 CREATE TABLE employee_contact ( employee_id BIGINT PRIMARY KEY, phone VARCHAR(255), email VARCHAR(255), CONSTRAINT fk_employee_contact FOREIGN KEY (employee_id) REFERENCES employee (id) );


## @ElementCollection / @CollectionTable
- 엔티티와 함께 저장, 조회, 업데이트, 삭제될 수 있는 비엔티티의 컬렉션을 정의할 수 있다.
  비엔티티 컬렉션은 주로 단순한 값(예: 문자열, 정수 등) 또는 @Embeddable 어노테이션이 붙은 클래스(복합 값 타입)를 사용한다.
- `@ElementCollection` 어노테이션을 단독으로 사용할 경우 추가 테이블이 생성 될 수 있다.
  `@CollectionTable` 어노테이션을 함께 사용하여 테이블을 지정하여 사용하는 것이 좋다.
- `@ElementCollection` 으로 정의된 컬렉션은 소유 엔티티의 생명주기에 종속된다.
  즉, 소유 엔티티가 삭제되면 컬렉션 내의 모든 요소도 함께 삭제된다.(변경도 마찬가지)

``` java
@Entity
public class User {
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(name = "user_phone_numbers", joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "phone_number")
    private Set<String> phoneNumbers;

    // ...
}

@OrderColumn

@Entity
public class User {
    @Id
    private Long id;

    @ElementCollection
    @OrderColumn(name = "list_order")
    private List<String> phoneNumbers;

    // ...
}

@Inheritance

@Entity @DiscriminatorValue("CAR") public class Car extends Vehicle { // Car 특유의 필드... }

@Entity @DiscriminatorValue("BIKE") public class Bike extends Vehicle { // Bike 특유의 필드... }

## MappedSuperclass
- 상속과 같은 계층 구조에서 엔티티가 공통적으로 가지는 속성이나 메소드를 정의하기 위해 사용한다. 
- 사용시 해당 클래스 자체는 엔티티가 아니며 직접적으로 데이터베이스 테이블과 매핑되지 않는다.
  > 예시1) 여러 엔티티에서 공유되는 필드(예: id, 생성 날짜, 수정 날짜 등)를 중복 없이 정의
  > 예시2) 공통적으로 사용되는 메소드(예: 필드 값 검증 또는 계산 메소드)를 중복 없이 정의
- 추상 클래스(abstract)를 사용하여 의도를 명확하게 하는 것이 좋다.
  (추상 클래스 자체가 상 사용하기 위해서는 상속이 필요하기 때문에

```java
@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedAt;

    // 기본적인 접근자(getter)와 설정자(setter) 메소드...
}

@Entity
public class User extends BaseEntity {
    private String name;
    // 추가적인 필드와 메소드...
}

@Entity
public class Product extends BaseEntity {
    private String name;
    // 추가적인 필드와 메소드...
}