김영한, ⌜자바 ORM 표준 JPA 프로그래밍⌟ 과
인프런 강의 <자바 ORM 표준 JPA 프로그래밍 - 기본편> 으로
공부한 JPA를 정리한 내용이다.
JPA를 사용하는 데 가장 중요한 일은 엔티티와 테이블을 정확히 매핑하는 것이다. (정적/설계적 측면)
대표 매핑 어노테이션
@Entity
@Table
@Id
@Colum
JPA 사용으로 테이블과 매핑할 클래스는 필수로 붙여야 함.
JPA가 관리하는 클래스가 되게 해주지
속성 | 기능 | 기본값 |
---|---|---|
name | 엔티티 이름 지정. 다른 패키지에 같은 이름의 엔티티클래스가 있다면 이름을 지정해 충돌하지 않게 해야 함. | 클래스이름 고대로 |
엔티티와 매핑할 테이블 지정
속성 | 기능 | 기본값 |
---|---|---|
name | 매핑할 테이블 이름 | 엔티티 이름 사용 |
catalog | catalog기능이 있는 DB에서 catalog매핑 | |
schema | schema기능이 있는 DB에서 schema매핑 | |
uniqueConstraints (DDL) | DDL 생성 시 유니크 제약조건 생성 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용됨 |
객체 필드를 테이블 컬럼에 매핑
속성 | 기능 | 기본값 |
---|---|---|
name | 컬럼 이름 지정 | 객체의 필드 이름 |
insertable/updatable (거의 사용하지 않음) | 엔티티 저장/수정 시 해당 필드도 같이 저장/수정 false -> 저장/수정 안함. 읽기 전용일 떄 사용 | true |
table (거의 사용하지 않음) | 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용 | 현재 클래스가 매핑된 테이블 |
nullable (DDL) | null값 허용 여부 false -> DDL 생성 시 not null 제약조건 | true |
unique (DDL) | 유니크제약조건. 키가 복잡한 이름으로 설정됨@Table.uniqueConstraints (키 이름 설정 가능)와 같음DDL) alter table Tablename add constraint UK_Xxx unique (username) | |
columnDefinition (DDL) | 직접 컬럼 정보 설정 ex) "varchar(100) default 'EMPTY'" | 필드의 자바 타입과 방언 정보를 사용해 적절한 컬럼 타입 생성 |
length (DDL) | 문자길이 제약조건. String 타입에만 사용 | 255 |
precision, scale (DDL) | BigDecimal타입에서 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용 | precision=19, scale=2 |
@Column 속성의 기본값 적용
예외
자바 기본타입(Primitive Type): null값 입력할 수 없음
-> nullable 속성 예외
// @Column 생략, 자바 기본타입
int data1;
data1 integer not null // 생성된 DDL
// @Column 생략, 객체 타입
Integer data2;
data2 integer // 생성된 DDL
// 객체타입일 때만 null값 허용
// @Column 사용, 자바 기본 타입
@Column
int data3;
data3 integer // 생성된 DDL
// @Column 사용하면 기본값이 true이기 때문에 nullabe=false로 지정하는 것이 안전함
enum 타입 매핑 시 사용
속성 | 기능 | 기본값 |
---|---|---|
value | EnumType.ORDINAL: enum 순서를 DB에 저장 EnumType.String: enum 이름을 DB에 저장 | EnumType.ORDINAL |
JPA가 엔티티 데이터에 접근하는 방식 지정
AccessType.FIELD
필드에 직접 접근. 필드 접근 권한이 private이어도 접근 가능AccessType.PROPERTY
접근자 사용설정하지 않으면 @Id
위치를 기준으로 접근방식 설정
@Id
@GeneratedValue
대리키 사용 방식@GeneratedValue(strategy=GenerationType.___
MySQL의 auto_increment
기능
em.persist()
호출 즉시 INSERT SQL 데이터베이스에 전달시퀀스: 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트
시퀀스를 지원하는 데이터베이스에서 사용 가능 - 오라클, PostgreSQL, 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;
시퀀스 생성 DDL) create sequence member_seq{시퀀스이름} start with 1{이니셜밸류} increment by 1{얼로케이션사이즈}
...
tx.begin();
try {
Member member = new Member();
member.setName("sese");
System.out.println("================");
em.persist(member); // 호출 시 시퀀스 사용해 식별자 조회->엔티티할당 후 영속성 컨텍스트 저장
System.out.println("member.id = "+member.getId());
System.out.println("================");
tx.commit(); // 플러시-> 인서트쿼리
}
...
// 출력문
================
Hibernate:
call next value for member_seq
member.id = 1
================
Hibernate:
/* insert hello.jpa.Member
*/ insert
...
속성 | 기능 | 기본값 |
---|---|---|
name | 식별자 생성기 이름 | 필수 |
sequenceName | 디비등록되있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시 처음 시작하는 수 지정 | 1 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수 | 50 |
시퀀스 전략은 시퀀스를 통해 식별자를 조회하는 추가 작업이 필요하기 때문에 데이터베이스와 2번 통신하게 됨. 인서트를 두 번 하면 시퀀스 접근도 두 번 해야됨 그래서 JPA가 시퀀스에 접근하는 횟수를 줄이기 위해 @SequenceGenerator.allocationSize
을 사용함
기본값으로 설정하면 한 번에 시퀀스 값을 50 증가시키고 1~50까지는 메모리에서 식별자를 할당함 그리고 51이 되면 시퀀스 값을 100으로 증가시킴 이러면 동시성 문제가 없음
키 생성 전용 테이블을 만들고 이름과 값으로 사용할 컬럼을 만들어 더이터베이스 시퀀스를 흉내내는 전략으로 모든 데이터베이스에 적용할 수 있다는 장점이 있지만 성능면에서는 떨어지는 단점이 있음
Long형 + 대체키 + 키 생성전략 사용
hibernate.hbm2ddl.auto
속성을 추가하면 실행 시점에 데이터베이스 테이블을 자동으로 설정함
옵션 | 설명 |
---|---|
create | 기존 테이블 삭제하고 새로 생성 DROP + CREATE |
create-drop | create+어플리케이션 종료 시 생성한 DDL 제거 DROP + CREATE + DROP |
update | 데이블과 엔티티 매핑정보를 비교해 변경사항만 수정. only 추가, 삭제는 안됨 |
validate | 테이블과 엔티티를 비교해서 차이가 있으면 경고를 남기고 어플리케이션 실행은 안함. DDL수정 안함 |
none | 자동생성기능 사용 안함 |