ddl-auto 설정값과 함께 사용할 경우 제약 조건을 설정 할 수 있다.
하지만 어디까지나 개발용도로만 사용하는 것이 좋다.
ddl-auto 설정 : JPA 구현체(예: Hibernate)가 어떻게 데이터베이스 스키마를 생성하고 관리할 것인지를 지정 할 수 있다.
indexes : 테이블에 인덱스 설정을 할 수 있다.
이것 또한 ddl-auto 설정값과 함께 사용할 수 있기 때문에 해당 설정값이 none 또는 validate 인 경우 변경을 자동으로 수행하지
않기 때문에 인덱스에 영향을 주지 않는다.
@Entity
@Table(name = "my_table", schema = "my_schema", catalog = "my_catalog", uniqueConstraints = {
@UniqueConstraint(columnNames = {"column1", "column2"})
}, indexes = {
@Index(name = "my_index", columnList = "column1, column2", unique = true)
})
public class MyEntity {
// 클래스 정의
}
## @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
양방향 관계에서 소유가 아닌 쪽에서 사용
cascade
한 엔티티에 대한 연산(저장, 업데이트, 삭제)이 그 엔티티와 관계를 맺고 있는 다른 엔티티에도 적용되도록 한다.
예시) Post 엔티티가 여러 Comment 엔티티를 소유하는 경우. Post 엔티티를 저장할 때 자동으로 모든 Comment 엔티티도 저장하려면 CascadeType.PERSIST나 CascadeType.ALL을 사용할 수 있다.
fetch
엔티티 간의 관계에서 관련된 엔티티를 어떻게 로딩할지를 정의하는데 사용한다.
예시1) User 엔티티가 있고, 각 User에 대한 Profile 정보가 거의 항상 필요한 경우, User와 Profile 사이의 관계에 FetchType.EAGER를 사용한다.
예시2) Author 엔티티가 여러 Book 엔티티와 관계가 있고, Author 정보를 조회할 때마다 모든 Book 정보가 필요하지 않은 경우, Author와 Book의 관계에 FetchType.LAZY를 사용한다.
이때 Book 에 대한 정보는 실제 사용되는 시점에 로드 된다.
optional
주로 @OneToOne 및 @ManyToOne 관계에서 사용되며, 이는 관계가 선택적인지(즉, null이 허용되는지) 여부를 나타낸다.
예시1) Employee 엔티티가 있고, Department 엔티티와 관계가 있지만 모든 직원이 특정 부서에 속하지 않을 수 있는 경우(Employee가 프리랜서일 수도 있음), @ManyToOne(optional = true)를 사용한다.
예시2) Order 엔티티가 있고, 각 Order가 반드시 Customer 엔티티와 관계를 맺어야 하는 경우, @ManyToOne(optional = false)를 사용한다.
orphanRemoval
@OneToOne 또는 @OneToMany 관계에서 사용된다. 부모 엔티티와 연결된 자식 엔티티가 부모와의 연결이 끊어진 상태가 될 때 해당 자식 엔티티를 자동으로 삭제하는 기능을 제공한다.
예시1) 값이 true일 때 부모 엔티티에서 자식 엔티티의 참조가 제거되면, 그 자식 엔티티는 자동으로 삭제됩니다.
예시2) 값이 false일 때(기본값): 부모 엔티티에서 자식 엔티티의 참조가 제거되어도 자식 엔티티는 데이터베이스에 남아 있습니다.
@Embeddable / @Embedded
엔티티 클래스 안에 있는 다수의 필드를 하나의 클래스로 묶어서 사용 할 수 있다.
아래 코드를 보면 Customer 엔티티 클래스 안에 필드값을 Address 클래스에 정의하여 사용하고 있다.
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Embedded
private Address address;
// 생성자, Getter 및 Setter 메서드들...
}
---
@Embeddable
public class Address {
@Column(name = "street")
private String street;
@Column(name = "city")
private String city;
@Column(name = "zipcode")
private String zipcode;
// 생성자, Getter 및 Setter 메서드들...
}
- 추가로 @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
한 엔티티에 대한 데이터가 물리적으로 여러 테이블에 분산되어 저장되어야 하는 상황에서 필요
import javax.persistence.*;
@Entity
@Table(name = "employee")
@SecondaryTable(name = "employee_contact", pkJoinColumns = @PrimaryKeyJoinColumn(name = "employee_id"))
public class Employee {
## @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
상속 관계를 가진 엔티티 클래스들을 매핑하는 데 사용한다.
옵션
strategy
InheritanceType.SINGLE_TABLE (기본값)
예시) Vehicle이라는 슈퍼 클래스가 있고 Car, Bike 등의 서브 클래스가 있다고 가정. 이 경우 모든 Car와 Bike 인스턴스는 단일 Vehicle 테이블에 저장한다.
InheritanceType.TABLE_PER_CLASS
예시) Product라는 슈퍼 클래스가 있고, Book과 Electronics라는 서브 클래스가 있다고 가정. 여기서 Book과 Electronics는 각각 별도의 테이블을 가진다.
InheritanceType.JOINED
예시) Employee라는 슈퍼 클래스가 있고, Manager와 Engineer라는 서브 클래스가 있다고 가정. Employee 테이블은 공통 필드(예: 이름, 주소)를 저장하고, Manager와 Engineer 테이블은 각각 특정 역할에 관련된 필드를 저장한다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "VEHICLE_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class Vehicle {
// 공통 필드...
}
@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;
// 추가적인 필드와 메소드...
}
@Entity
name
: 기본값은 클래스 이름이며 엔티티의 이름을 설정한다.@Table
name
: 기본값은 클래스 이름이며 데이터베이스의 특정 테이블과 매핑하는데 사용된다.uniqueConstraints
: 테이블에 유니크 제약 조건을 지정 할 수 있다.indexes
: 테이블에 인덱스 설정을 할 수 있다.@OneToOne / @OneToMany / @ManyToOne / @ManyToMany
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
cascade
fetch
optional
orphanRemoval
@Embeddable / @Embedded
아래 코드를 보면 Customer 엔티티 클래스 안에 필드값을 Address 클래스에 정의하여 사용하고 있다.
@SecondaryTable
@Entity @Table(name = "employee") @SecondaryTable(name = "employee_contact", pkJoinColumns = @PrimaryKeyJoinColumn(name = "employee_id")) public class Employee {
}
-- 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) );
@OrderColumn
@Inheritance
strategy
@Entity @DiscriminatorValue("CAR") public class Car extends Vehicle { // Car 특유의 필드... }
@Entity @DiscriminatorValue("BIKE") public class Bike extends Vehicle { // Bike 특유의 필드... }