인프런 강의 < 자바 ORM 표준 JPA 프로그래밍 - 기본편 > 정리
JPA를 사용하는데 가장 중요한일은 엔티티와 테이블을 정확히 매핑하는 것이므로 매핑 어노테이션을 숙지해야한다.
JPA가 지원하는 매핑 어노테이션에는 총 아래와 같이 4가지로 분류된다.
JPA를 사용해서 테이블과 매핑할 클래스에 꼭 붙여야 한다.
| 속성 | 기능 | 기본값 |
|---|---|---|
| name | JPA에서 사용할 엔티티 이름을 지정하며 보통 클래스 이름을 사용한다. | 설정하지 않으면 클래스 이름을 그대로 사용 |
public Member(){} // 직접 선언
public Member(String name) {this.name = name;} // 이미 선언되어있는 생성자@Table은 엔티티와 매핑할 테이블을 지정하며 생략시 매핑한 엔티티 이름을 테이블 이름으로 사용한다.
| 속성 | 기능 | 기본값 |
|---|---|---|
| name | 매핑할 테이블 이름 | 엔티티 이름 사용 |
| catalog | catalog 기능이 있는 db에서 catalog를 매핑한다 | |
| schema | schema 기능이 있는 db에서 schema를 매핑한다 | |
| DDL 생성 시, 유니크 제약조건을 만든다. 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용 |
JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.
클래스의 매핑정보를 보면 어떤 테이블의 어떤 컬럼을 사용하는지 알 수 있으므로 JPA는 매핑정보와 데이터베이스 방언을 사용해 스키마를 생성한다.
애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성하기 위해서
<property name="hibernate.hbm2ddl.auto" value="create" /> 속성을 추가하면 된다.
스키마 자동생성 기능을 사용하면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성하므로 개발자의 수고를 덜 수 있다.
하지만 DDL(Data Definition Language)은 완벽하지 않으므로 운영 환경 말고, 개발 환경에서 사용하거나 매핑을 어떻게 해야하는지 참고용으로 사용하는 것이 좋다.
| 옵션 | 설명 |
|---|---|
| create | 기존 테이블을 삭제하고 새로 생성. DROP/CREATE |
| create-drop | create 속성에 추가로 삭제. DROP/CREATE/DROP |
| update | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경사항 수정 |
| validate | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 보낸다. 애플리케이션을 실행하지 않고 DDL을 수정하지 않는다. |
| none | 자동 생성 기능을 사용하지 않으려면 hibernate.hbm2ddl.auto속성을 삭제하거나 none으로 해주면 된다. |
운영장비에는 create, create-drop, update 사용 금지create, updateupdate, validatevalidate, none| 분류 | 매핑 어노테이션 | 설명 |
|---|---|---|
| @Column | 컬럼 매핑 | |
| @Enumerated | 자바의 enum타입 매핑 | |
| @Temporal | 날짜 타입 매핑 | |
| @Lob | BLOB, CLOB 타입 매핑 | |
| @Transient | 특정 필드를 데이터베이스에 매핑하지 않는다. | |
| 기타 | @Access | JPA가 엔티티에 접근하는 방식 지정 |
@Column은 객체 필드를 테이블 컬럼에 매핑한다. @Column속성중에 name, nullable외에는 거의 사용되지 않는다.
| 속성 | 기능 | 기본값 |
|---|---|---|
| name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
| insertable | 엔티티 저장 시, 이 필드도 같이 저장한다. false로 설정하면 이 필드는 db에 저장하지 않는다 | true |
| updatable | 엔티티 수정 시, 이 필드도 같이 수정한다. false로 설정하면 db에 수정하지 않는다. | true |
| table | 하나의 엔티티를 두 개 이상의 테이블에 매핑할 떄 사용한다. 지정한 필드를 다른 테이블에 매핑 가능 | 현재 클래스가 매핑된 테이블 |
| nullable(DDL) | null값의 허용 여부 설정, false면 not null 제약붙음 | true |
| unique(DDL) | 한 컬럼에 간단히 유니크 제약조건 걸때 사용 | |
| columnDefinition | 데이터베이스 컬럼 정보를 직접 줄 수 있다. | 필드의 자바 타입과 방언 정보를 사용해서 적절한 컬럼 타입을 생성한다. |
| length(DDL) | 문자 길이 제약조건, String 타입에만 사용 | 255 |
| precision, scale(DDL) | BigDecimal 타입에서 사용한다.(BigInteger도 사용가능), precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수다(double, float타입에는 적용되지 않는다.) | precision=19, scale=2 |
| 속성 | 기능 | 기본값 |
|---|---|---|
| value | 1. EnumType.ORDINAL: enum 순서를 데이터베이스에 저장 2. EnumType.STRING: enum 이름을 데이터베이스에 저장 | EnumType.ORDINAL |
enum RoleType {
ADMIN, USER
}
ORDINAL 사용하지 말고 STRING 사용하지만 기존 db에는 여전히 1번으로 남아 있기 때문에 사용 XEnumType.ORDINAL은 enum에 정의된 순서대로 ADMIN은 0, USRE는 1 값이 데이터베이스에 저장된다
EnumType.STRING은 enum 이름 그대로 ADMIN은 'ADMIN', USER는 'USER'라는 문자로 데이터베이스에 저장된다.
날짜 타입(java.util.Date, java.util.Calendar)을 매핑할때 사용한다.
| 속성 | 기능 | 기본값 |
|---|---|---|
| value | 1. TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑 2. TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑 3. TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑/TemporalType은 필수로 지정 해야함 |
@Temporal을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의 된다.
@Lob에는 지정할 수 있는 속성이 없다.
매핑하는 필드 타입이 문자면 CLOB으로 매핑, 나머지는 BLOB으로 매핑
객체이 임시로 어떤 값을 보관하고 싶을 떄 사용
JPA가 엔티티 데이터ㅔ 접근하는 방식을 지정
@Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식 설정직접 할당: 기본 키를 애플리케이션에서 직접 할당한다.
자동 생성: 대리 키 사용 방식
자동 생성 전략이 다양한 이유는 데이터베이스 벤더마다 지원하는 방식이 다르기 때문(ex. 오라클은 시퀀스 제공하지만 mysql은 제공하지 않고 기본 키 값을 자동으로 채워주는 AUTO_INCREMENT 기능제공)
직접할당을 하려면 @Id를 매핑하면 된다.
@Id
@Column(name = "id")
private String id;
기본 키 직접 할당은 persist()로 엔티티를 저장하기 전에 애플리케이션에서 기본 키를 직접 할당하는 방법
Board board = new Board();
board.setId("id1") // 기본 키 직접할당
em.persist(board);
IDENTITY는 기본 키 생성을 데이터베이스 위임하는 전략이다.
CREATE TABLE BOARD (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
DATA VARCHAR(255)
);
INSERT INTO BOARD(DATA) VALUES('A');
INSERT INTO BOARD(DATA) VALUES('B');
AUTO_INCRMENT를 추가해서 데이터베이스 값을 저장할때 ID 컬럼을 비워두면 데이터베이스가 순서대로 값을 채워준다.
사용방법은 @GeneratedValue 어노테이션을 사용하고 strategy = GEnerationType.IDENTITY를 사용하면 된다.
IDENTITY 전략은 데이터를 데이터베이스에 INSERT한 후에 기본 키 값을 조회할 수 있다.
따라서 엔티티에 식별자 값을 할당하려면 JPA는 추가로 데이터베이스를 조회해야 한다.
또한 데이터베이스를 저장해야 식별자를 구할 수 있으므로, em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달된다.
따라서 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
데이터베이스 시퀀스는 유일한 값을 생성하는 특별한 데이터베이스 오브젝트
@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;
@SequenceGenerator
| 속성 | 설명 | 기본값 |
|---|---|---|
| name | 식별자 생성기 이름 | 필수 |
| sequenceName | 데이터베이스에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
| initialValue | DDL생성 시 사용됨. 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정 | 1 |
| allocationSize | 시퀀스 한 번 호출에 증가하는 수 | 50 |
| catalog, schema | 데이터베이스 catalog, schema 이름 |
키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}

기본 키 제약 조건: null 아님, 유일, 변하면 안됨
주민등록번호 같은 것은 기본 키로 적절하지 않음 -> 자연키보단 대체키 사용
< 자료 출처: 자바 ORM 표준 JPA 프로그래밍 - 기본편 >