핵심 어노테이션
@Entity
•
@Entity 어노테이션이 붙은 클래스는 JPA가 관리하는 엔티티이다
•
JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션이 필수다
•
기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
•
final 클래스, enum, interface, inner 클래스 사용 X
•
저장할 필드에 final 사용 X
•
name 속성을 사용하면 JPA에서 사용할 엔티티 이름을 지정할 수 있다.
◦
기본값은 클래스 이름을 그대로 사용한다
예시:
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
Member(){}// 생략하면 자동으로 생성 but, 다른 생성자가 있으면 자동 생성 안됨
}
Java
복사
@Table
•
@Table 어노테이션은 엔티티와 매핑할 테이블을 지정한다.
•
name 속성으로 매핑할 테이블 이름 지정이 가능하다
•
기본값은 엔티티 이름이다
예시 :
@Entity
@Table(name = MEMBERS)
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
Member(){}// 생략하면 자동으로 생성 but, 다른 생성자가 있으면 자동 생성 안됨
}
Java
복사
필드와 칼럼 매핑
@Entity
public class Member {
@Id
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
//Getter, Setter…
}
Java
복사
1. @Column
속성 | 설명 | 기본값 |
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable,updatable | 등록, 변경 가능 여부 | TRUE |
nullable(DDL) | null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다. | |
unique(DDL) | @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다. | |
columnDefinition(DDL) | 데이터베이스 컬럼 정보를 직접 줄 수 있다.ex) varchar(100) default ‘EMPTY' | 필드의 자바 타입과방언 정보를 사용해 |
length(DDL) | 문자 길이 제약조건, String 타입에만 사용한다. | 255 |
precision,scale(DDL) | BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다).precision은 소수점을 포함한 전체 자 릿수를, scale은 소수의 자릿수다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나정 밀한 소수를 다루어야 할 때만 사용한다 | precision=19,scale=2 |
2. @Enumerated
•
자바 enum 타입을 매핑할 때 사용
속성 | 설명 | 기본값 |
value | - EnumType.ORDINAL: enum 순서를 데이터베이스에 저장- EnumType.STRING: enum 이름을 데이터베이스에 저장 | EnumType.ORDINAL |
기본값은 ORDINAL이지만, ORDINAL을 사용하지 않는 게 좋다.
예를 들어
public enum RollType {
ACTOR, PROGRAMMER, CEO// 0,1,2
}
Java
복사
위와 같은 enum 타입 클래스를 정의했다고 하자.
ACTOR, PROGRAMMER, CEO는 순서대로 0,1,2를 나타낸다.
만약 value 속성을 @Enumerated(value = EnumType.ORDINAL)로 하면 순서인 0,1,2를 저장한다
이때 RollType이 아래와 같이 변한다고 하자.
public enum RollType {
DANCER, ACTOR, PROGRAMMER, CEO// 0,1,2,3
}
Java
복사
DANCER라는 값이 앞에 추가되면서 기존의 순서가 깨져버린다. 이렇게 되면 데이터베이스에 저장된 ACTOR=0, PROGRAMMER=1, CEO=2 등의 순서와 정합성이 맞지 않게 된다.
반면 EnumType.STRING을 사용하면 enum 이름 그대로 저장하기 때문에 enum 값이 변하더라도 문제가 없다.
@Temporal
•
날짜 타입(java.util.Date, java.util.Calender)을 매핑할 때 사용
•
최신 하이버네이트가 지원하는 LocalDate, LocalDateTime을 사용할 때는 생략 가능하다.
속성 | 설명 | 기본값 |
value | • TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑(예: 2013–10–11)• TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑(예: 11:11:11)• TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이 스timestamp 타입과 매핑(예: 2013–10–11 11:11:11) |
@Lob
•
데이터베이스 BLOB, CLOB 타입과 매핑
•
지정할 수 있는 속성이 없다
•
매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
@Transient
•
해당 어노테이션이 붙은 필드는 매핑하지 않는다
•
따라서 데이터베이스에 저장되지도, 조회되지도 않는다
•
주로 메모리상에서만 임시로 값을 보관하고 싶을 때 사용한다
기본키 매핑 어노테이션
•
직접 기본키를 할당하려면 @Id 어노테이션만 사용
•
자동 생성하려면 @GeneratedValue 어노테이션 사용
@GeneratedValue
IDENTITY 전략
•
기본 키 생성을 데이터베이스에 위임
•
주로 MySQL, PostgreSQL, SQL Server, DB2 등에서 사용 (예시 : MySQL의 AUTO_INCREMENT)
•
JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL을 실행한다
•
AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있다
•
IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 후 DB에서 식별자를 조회한다
예시 :
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
Java
복사
SEQUENCE 전략
•
유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트(예시 : 오라클 시퀀스)
•
오라클, PostgreSQL, DB2, H2 데이터베이스 등에서 사용
예시 :
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
Java
복사
속성 | 설명 | 기본값 |
name | 식별자 생성기 이름 | 필수 |
sequenceName | 데이터베이스에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는수를 지정한다. | 1 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨)데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다 | 50 |
catalog, schema | 데이터베이스 catalog, schema 이름 |
TABLE 전략
•
키 생성 전용 테이블을 하나 만들어 데이터베이스 시퀀스를 흉내 내는 전략
•
모든 데이터베이스에 적용 가능하지만 성능이 좋지 않다
•
TABLE 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터 베이스 시퀀스를 흉내 내는 전략이다. 이 전략은 테이블을 사용하므로 모든 데이터베이스에 적용할 수 있다.
•
TABLE 전략은 시퀀스 대신에 테이블을 사용한다는 것만 제외하면 SEQUENCE 전략과 내부 동작방식이 같다.
•
@TableGenerator 어노테이션에 적용할 수 있는 속성은 아래와 같다. (기본 값은 하이버네이트 기준)
•
name :
◦
식별자 생성기 이름을 설정가능하며 기본 값이 필수
◦
table:
▪
키생성 테이블명
▪
기본값 = hibernate_sequence
◦
pkColumnName :
▪
시퀀스 컬럼명
▪
기본값 = sequence_name
◦
valueColumnName :
▪
시퀀스 값 컬럼명
▪
기본값 = next_val
◦
pkColumnValue :
▪
키로 사용할 값 이름
▪
기본값 = Entity 명
◦
initialValue :
▪
초기 값, 마지막으로 생성된 값이 기 준이다.
▪
기본값 = 0
◦
allocationSize :
▪
시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨)
▪
기본값 = 50
◦
catalog, schema :
▪
데이터베이스 catalog,schema 명
◦
uniqueConstraints(DDL) :
▪
유니크 제약 조건을 지정할 수 있다.
◦
TABLE 전략은 SELECT 쿼리로 값을 조회하고 UPDATE 쿼리로 값을 증가시킨다. SEQUENCE 전략과 비교했을때 DB와 한 번 더 통신하는 것이 단점이다. TABLE 전략 최적화는 @TableGenerator.allocationSize 를 사용하면 된다. 해당 어노테이션을 사용하면 SEQUENCE 전략과 같아진다.
•
Core Annotations
◦
@entity on Entity class -> make members persistence(MANAGED)
•
@table(name = "blog") -> make class as DB table
◦
@id -> make PK
▪
@GeneratedValue -> strategy of PK option
▪
- TABLE -> make table for only PK?
▪
- SEQUENCE -> need to create sequence as Oracle DB, H2, PostgreSQL etc..
▪
- IDENTITY -> PK creation assign to DB as MySQL, MySQL DB increase num by auto_increment
▪
- AUTO -> JPA decides by DATA Type
▪
-- if, UUID -> UUID Generator
▪
-- if, Numerial(int, long...) -> Default Sequence but there's no Sequence like MySQL -> choose Table Automatically.
•
@column -> make field as DB column with attributes
•
@MappedSuperclass -> make class as static variable for only Entity object(DB's row)
•
@EntityListeners(AuditingEntityListener.class) -> when DB operation happening, this class's working dynamically with operation like insert User row, Listners action right away with it.
◦
- follow details : https://mopil.tistory.com/46
•
@TemporaL(TemporalType.TIMESTAMP) <- default TIMESTAMP
◦
- Optional type
◦
-- DATE(YYYY-MM-DD)
◦
-- TIME(HH:MM:SS)
◦
-- TIMESTAMP(YYYY-MM-DD HH:MM:SS) as DATE+TIME
▪
date는 날짜까지만 나타나기때문에 시간분초까지 나타나는 datetime타입을 선택.
▪
게시글이기 때문에 장문이 들어 올 수 있어 text타입 → @column(columnDefinition = "TEXT")