JPA를 이용해 데이터베이스의 테이블과 상호 작용(데이터 저장, 수정, 조회, 삭제 등)하기 위해 가장 우선되는 작업은 데이터베이스의 테이블과 엔티티 클래스 간의 매핑 작업니다.
엔티티 매핑 작업은 크게 객체와 테이블 간의 매핑, 기본키 매핑, 필드(멤버 변수)와 컬럼 간의 매핑, 엔티티 간의 연관 관계 매핑 등으로 나눌 수 있다.
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity(name = "USERS") // (1)
@Table(name = "USERS") // (2)
public class Member {
@Id
private Long memberId;
}
@Entity
애너테이션@Table
애너테이션@Table
애너테이션은 옵션이며, 추가하지 않을 경우 클래스 이름을 테이블 이름으로 사용한다.@Table
애너테이션은 옵션이지만 @Entity
와 @ID
애너테이션은 필수이다.@Entity
와 @ID
애너테이션은 함께 사용한다.@Entity
애너테이션만 추가하고 식별자 역할을 하는 필드(멤버 변수)에 @ID
애너테이션을 추가하지 않으면 다음과 같은 에러가 발생한다.Caused by: org.hibernate.AnnotationException: No identifier specified for entity:...
@Entity
와 @Table
애너테이션에 name
애트리뷰트를 지정하지 않고, 클래스 이름으로 사용하는 것을 권장한다.데이터베이스의 테이블에 기본키 설정은 필수라고 할 수 있다.
JPA에서는 기본적으로 @ID
애너테이션을 추가한 필드가 기본 키 컬럼이 되는데, JPA에서는 기본키를 어떤 방식으로 생성해 줄지에 대한 다양한 전략을 지원한다.
@NoArgsConstructor
@Getter
@Entity
public class Member {
@Id // (1)
private Long memberId;
public Member(Long memberId) {
this.memberId = memberId;
}
}
@NoArgsConstructor
@Getter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // (1)
private Long memberId;
public Member(Long memberId) {
this.memberId = memberId;
}
}
@NoArgsConstructor
@Getter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE) // (1)
private Long memberId;
public Member(Long memberId) {
this.memberId = memberId;
}
}
@NoArgsConstructor
@Getter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO) // (1)
private Long memberId;
public Member(Long memberId) {
this.memberId = memberId;
}
}
@Column
애너테이션은 필드와 컬럼을 매핑해주는 애너테이션이다. 만약, @Column
애너테이션이 없고, 필드만 정의되어 있다면 JPA는 기본적으로 이 필드가 테이블의 컬럼과 매핑되는 필드라고 간주하게 된다. 또한, @Column
애너테이션이 사용되는 애트리뷰트의 값은 디폴트 값이 모두 적용된다.null
값을 허용할 지 여부를 지정true
false
로 지정함true
false
로 지정false
true
로 지정@Column
애너테이션이 생략되었거나 애트리뷰트가 기본값을 사용할 경우 주의사항@Column
애너테이션이 생략되면 기본적으로 nullable=false
이다.int price not null
이라는 조건으로 컬럼을 설정하길 원하는데 nullable에 대한 명시적인 설정 없이 @Column
애너테이션만 추가하면 nullable=true
가 기본값이 되기 때문에 테이블에는 int price
와 같이 설정될 것이다.int price not null
일 경우, @Column(nullable=false)
라고 명시적으로 지정하거나 @Column
애너테이션 자체를 사용하지 않는 것이 권장된다.@NoArgsConstructor
@Getter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long memberId;
// (1)
@Column(nullable = false, updatable = false, unique = true)
private String email;
...
...
public Member(String email) {
this.email = email;
}
}
@Entity
와 @Id
애너테이션만 추가한다.@Column
정보를 명시적으로 모두 지정하는 것은 번거롭긴하지만 다른 누군가가 엔티티 클래스 코드를 확인하더라도 테이블 설계가 어떤식으로 되어 있는지 한눈에 알 수 있다는 장점이 있다.@Enumerated
애너테이션을 사용할 때 EnumType.ORDINAL
을 사용할 경우, enum의 순서가 뒤바뀔 가능성도 있으므로 처음부터 EnumType.ORDINAL
대신에 EnumType.STRING
을 사용하는 것이 좋습니다.@Transient
애너테이션은 필드에 추가하면 테이블 컬럼과 매핑하지 않겠다는 의미로 JPA가 인식한다.