JPA를 사용하는 데 가장 중요한 일은 엔티티와 테이블을 정확히 매핑하는 것이다.
그러려면 JPA의 매핑 어노테이션을 잘 사용해야한다.
JPA가 지원하는 어노테이션은 크게 4가지로 분류할 수 있다.
- 🔗 객체와 테이블 매핑 : @Entity @Table
- 🔗 기본키 매핑 : @Id
- 필드와 컬럼 매핑 : @Column
- 🔗 연관관계 매핑 : @ManyToOne @JoinCloumn @OneToMany
annotation | 매핑 대상 |
---|---|
@Column | 컬럼 |
@Enumerated | 자바의 enum 타입 |
@Termporal | 날짜 타입 |
@Lob | BLOB, CLOB |
@Transient | 매핑 하지 않음 |
@Column
은 객체 필드를 테이블 컬럼에 매핑한다.
@Column
은 가장 많은 기능을 갖고 있는데, 다양한 속성들을 살펴보자.
(거의 사용하지 않는 속성은 제외하였다.)
속성명 | 기능 | Default |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼명 | 객체의 필드명 |
nullable (DDL) | null 값 허용 여부 설정 false로 설정하면 DDL 생성 시 not null 제약조건이 붙는다. | true |
unique (DDL) | 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다. 하지만 생성되는 제약조건 이름이 알아보기 힘든 문자로 생성되기 때문에 🔗@Table의 uniqueConstraints 속성을 이용해 name까지 같이 지정하는 방식을 더 많이 쓴다. | |
columnDefinition (DDL) | 데이터베이스 컬럼 정보를 직접 매핑 | 필드의 자바 타입과 방언 정보를 사용해 적절한 컬럼 타입 생성 |
length (DDL) | 문자 길이 제약조건 String 타입에만 사용 | 255 |
precision,scale (DDL) | BigDecimal/BigInteger 타입에서 사용 precision은 소수점을 포함한 전체 자리수 scale은 소수점 자리수 | precision=19, scale=2 |
@Column(nullable = false)
private String data;
// 생성된 DDL
// data varchar(255) not null
@Column(unique = true)
private String username;
// 생성된 DDL
// alter table TableName
// add constraint UK_Xxx unique (username)
@Column(columnDefinition = "varchar(100) default 'EMPTY'")
private String data;
// 생성된 DDL
// data varchar(100) default 'EMPTY'
@Column(length = 400)
private String data;
// 생성된 DDL
// data varchar(400)
@Column(precision =10, scale = 2)
private BigDecimal cal;
// 생성된 DDL
// cal numeric(10,2) H2, PostgreSQL
// cal number(10,2) Oracle
// cal decimal(10,2) MySQL
🚨
자바 데이터 타입(Primitive type)
과@Column
@Column
은 기본적으로nullable
이다.
때문에 null 값을 허용하지 않는자바 데이터 타입
의 경우@Column (nullable = false)
로 지정해야 안전하다. 만약,Integer
와 같은객체 타입(Reference Type)
이라면@Column
을 생략해도 무방하다.
자바의 enum
타입을 매핑할 때 유용하게 사용된다.
속성명 | 기능 | Default |
---|---|---|
value | - EnumType.ORDINAL : enum 순서를 저장 - EnumType.STRING : enum 이름을 저장 | EnumType.ORDINAL |
@Enumerated
를 사용할 때는 기본값인EnumType.ORDINAL
보다는
EnumType.STRING
을 사용하는 것이 안전하다.
💡 왜냐하면,enum
클래스 내부에 정의된 순서가 항상 같을 것이라는 보장이 없기 때문이다.enum
의 추가나 삭제 등으로 순서가 바뀌게 된다면, 데이터베이스 무결성을 해칠 수 있다.
다음과 같은 enum 클래스가 있을 경우
enum RoleType {
ADMIN, USER
}
Entity에는 이렇게 매핑을 한다.
@Enumerated(EnumType.STRING)
private RoleType roleType;
코드를 작성할 때, 아래처럼 사용하면 된다.
memebr.setRoleType(RoleType.ADMIN); // -> 테이블의 role_type 컬럼에 'ADMIN'으로 저장된다.
만약, EnumType.ORDINAL
로 매핑을 했을 경우엔
데이터베이스에는 ADMIN
이 아닌 0
값이 저장된다.
날짜 타입을 매핑할 때 사용한다. (java.util.Date
, java.util.Calendar
)
하지만 Java8 이상 부터 사용 가능한 LocalDate
, LocalDateTime
타입을 사용하면 생략 가능하다.
속성명 | 매핑대상 | Default |
---|---|---|
value | - TemporalType.DATE : 데이터베이스 date 타입 - TemporalType.TIME : 데이터베이스 time 타입 - TemporalType.TIMESTAMP : 데이터베이스 timestamp 타입 | 최신 Hibernate에선 생략해도 된다. (Java8 이상) |
@Temporal(TemporalType.DATE)
private Date date; //날짜
@Temporal(TemporalType.TIME)
private Date time; //시간
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp; //날짜와 시간
데이터베이스 BLOB
, CLOB
타입과 매핑한다.
@LOB
은 지정할 수 있는 속성이 없다.
매핑하는 필드 타입이 문자면 CLOB
으로 매핑하고, 나머지는 BLOB
으로 매핑한다.
@Transient
를 붙이면 해당 필드는 매핑하지 않는다.
데이터베이스에 저장하지 않고, 조회하지도 않기 때문에 객체에 임시로 값을 보관하고 싶을 때 사용한다.
강의_자바 ORM 표준 JPA 프로그래밍 - 기본편
교재_자바 ORM 표준 JPA 프로그래밍(김영한)다정한 피드백 환영해요 🤗