-
Notifications
You must be signed in to change notification settings - Fork 0
chap 4 minseong
MIN SEONG edited this page May 6, 2020
·
1 revision
- JPA 사용시 중요한 것 : 엔티티(Entity)와 테이블(Table) 매핑
- JPA의 매핑 어노테이션
- 객체와 테이블 매핑 :
@Entity
,@Table
- 기본 키 매핑 :
@Id
- 필드와 컬럼 매핑 :
@Column
- 연관관계 매핑 :
@ManyToOne
,@JoinColumn
- 객체와 테이블 매핑 :
- JPA를 사용해서 테이블과 매핑하는 클래스
- @Entity 속성
속성 | 기능 | 기본값 |
---|---|---|
name | JPA에서 사용할 엔티티 이름 지정 다른 패키지와 이름을 다르게 해야 한다 |
설정하지 않으면 클래스이름을 그대로 사용 |
- @Entity 적용 시 주의사항
- 기본 생성자 필수(파라미터가 없는 public, protected)
- final, enum, interface, inner 클래스 사용 불가
- 엔티티와 매핑할 테이블을 지정
- @Table 속성
속성 | 기능 | 기본값 |
---|---|---|
name | 매핑할 테이블 이름 | 엔티티 이름을 사용 |
catalog | 데이터베이스에 catalog 매핑 | |
schema | 데이터베이스에 schema 매핑 | |
uniqueConstraints(DDL) | DDL 생성 시에 유니크 제약 조건 생성 |
- JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원하여 클래스 매핑 정보를 보면 테이블에 어떤 컬럼을 사용하는지 알 수 있다
- persistence.xml에서 hibernate.hbm2ddl.auto 값 설정
- value="create" 설정시 애플리케이션 실행 시점에 데이터베이스 테이블이 있는지 확인하여 자동으로 생성해준다.
- 개발자가 테이블을 직접 생성할 필요가 없음
- 운영 환경에서 사용할만큼 완벽하지는 않으므로 개발 환경이나 참고용으로 사용하는 것이 좋음
- 설정시 콘솔에서 해당 테이블 생성 DDL을 출력
- value="create" 설정시 애플리케이션 실행 시점에 데이터베이스 테이블이 있는지 확인하여 자동으로 생성해준다.
- 자동 생성되는 DDL은 데이터베이스 방언에 따라 적절한 타입으로 생성
- hibernate.hbm2ddl.auto 속성
옵션 | 설명 |
---|---|
create | 기존 테이블을 삭제하고 새로 생성(DROP + CREATE) |
create-drop | create 속성 + 애플리케이션 종료시 생성한 DDL 제거(DROP + CREATE + DROP) |
update | 데이터베이스의 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정 |
validate | 데이터베이스의 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리캐이션을 실행하지 않음 DDL을 수정하지 않는다 |
none | 자동 생성 기능을 사용하지 않으려면 hibernate.hbm2ddl.auto 속성을 삭제한다 |
- JPA 2.1 버전부터는 스키마 자동 생성 기능을 표준으로 지원
// persistence.xml
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
- none, create, drop-and-create, drop
- hibernate.ejb.naming_strategy 속성 사용시 테이블명이나 컬럼명이 생략되어도 테이블 컬럼을 언더스코어 표기법으로 매핑
-
@Colume
매핑정보의 속성 값들- nullable : not null 제약 조건(false이면 not null)
- length : 문자 크기 지정
-
@Table
의 uniqueConstraints 속성
// Member.java
@Entity(name="Member")
@Table(name="MEMBER", uniqueConstraints = { @UniqueConstraint( // 추가
name = "NAME_AGE_UNIQUE",
columeNames = { "NAME", "AGE" } ) } )
public class Member {
...
}
- DDL 생성 기능들은 DDL을 자동 생성할 때만 사용되고 JPA 실행 로직에는 영향을 주지 않음
- JPA가 제공하는 데이터베이스 기본 키 생성 전략
- 직접 할당 : 기본 키를 애플리케이션에서 직접 할당(`@Id 사용)
- 자동 생성 : 대리 키 사용 방식. 데이터베이스가 생성해주는 값을 사용
- IDENTITY : 기본 키 생성을 데이터베이스에 위임
- SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당
- TABLE : 키 생성 테이블 사용
- 자동 생성 전략의 경우 데이터베이스 벤더마다 지원 방식이 다르므로 방법이 다양해짐
- 오라클의 시퀀스, MySQL의 AUTO_INCREMENT
- IDENTITY, SEQUENCE 전략의 경우 사용하는 데이터베이스에 의존적
- TABLE 전략의 경우 테이블을 활용하므로 모든 데이터베이스에서 사용
- persistence.xml에 hibrenate.id.new_generator_mappings=true 속성 추가
-
@Id
적용 가능 자바 타입 : 자바 기본형, 자바 래퍼형(Wrapper), String, java.util.Date, java.sql.Date, java.math.BigDecimal, java.math.BigInteger - 기본 키 직접 할당 전략은 persist()로 엔티티를 저장하기 전에 애플리케이션에서 기본 키를 직접 할당하는 방법
- 기본 키를 식별자 값 없이 저장 시 javax.persistence.PersistenceException 예외 발생
- 기본 키 생성을 데이터베이스에 위임하는 전략
- MySQL, PostgreSQL, SQL Server, DB2에서 사용
-
@GeneratedValue
의 strategy 속성 값을 GenerationType.IDENTITY로 지정 - JPA에서 IDENTITY 전략은 데이터를 데이터베이스에 INSERT한 후에 기본 키 값을 조회할 수 있음
- JDBC3에 추가된 Statement.getGeneratedKeys() 사용 시 데이터를 저장하면서 동시에 생성된 기본 키 값을 얻어옴
- IDENTITY 전략은 엔티티를 데이터베이스에 저장해야 식별자를 구할 수 있으므로 트랜잭션을 지원하는 쓰기 지연이 동작하지 않음
// Board.java
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
}
- 데이터베이스 시퀀스 : 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트
- 오라클, PostgreSQL, DB2, H2에서 사용
- persist() 호출 시 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회하여 엔티티에 할당한 후 영속성 컨텍스트에 저장한다. 그 후 트랜잭션 커밋시 플러시가 일어나 엔티티를 데이터베이스에 저장한다.
- JPA 표준 명세에서는 sequenceName의 기본값을 JPA 구현체가 정의하도록 함
-
@SequenceGenerator
속성
속성 | 기능 | 기본값 |
---|---|---|
name | 식별자 생성기 이름 | 필수 |
sqeuenceName | 데이터베이스에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정한다. |
1 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨) |
50 |
catalog, schema | 데이터베이스 catalog, schema 이름 |
// Board2.java
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ", // 매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1 )
public class Board2 {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
...
}
- 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략
create table MY_SEQUENCE (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)
-
JPA 표준 명세에서는 table, pkColumnName, valueColumnName의 기본값을 JPA 구현체가 정의하도록 함
-
SEQUENCE 전략과 비교해서 UPDATE를 위해 데이터베이스와 한 번 더 통신하는 단점이 있음
-
@TableGenerator
속성 정리
속성 | 기능 | 기본값 |
---|---|---|
name | 식별자 생성기 이름 | 필수 |
table | 키생성 테이블명 | hibernate_sequence |
pkColumnName | 시퀀스 컬럼명 | sequence_name |
valueColumnName | 시퀀스 값 컬럼명 | next_val |
pkColumnValue | 키로 사용할 값 이름 | 엔티티 이름 |
initialvalue | 초기 값, 마지막으로 생성된 값이 기준이다. | 0 |
allocationsize | 시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨) |
50 |
catalog, schema | 데이터베이스 catalog, schema 이름 | |
uniqueConstraints(DDL) | 유니크 제약 조건을 지정할 수 있다. |
// Board3.java
@Entity
@TableGenerator(
name = "BOARD_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "BOARD_SEQ", allocationSize = 1 )
public class Board3 {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
...
}
- GenerationType.AUTO : 선택한 데이터베이스 방언에 따라 세 전략 중 하나를 자동으로 선택
- 데이터베이스를 변경해도 코드를 수정할 필요가 없음
- SEQUENCE, TABLE 전략이 선택되면 시퀀스나 키 생성용 테이블을 미리 만들어 두어야 함
- 스키마 자동 생성 기능을 사용하면 하이버네이트가 기본값을 사용해서 적절한 시퀀스나 키 생성용 테이블을 만들어 줌
// Board4.java
@Entity
public class Board4 {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
- 직접 할당 : persist()를 호출하기 전에 애플리케이션에서 직접 식별자 값을 할당해야 한다. 만약 식별자 값이 없으면 예외가 발생
- SEQUENCE : 데이터베이스 시퀀스에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- TABLE : 데이터베이스 시퀀스 생성용 테이블에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- IDENTITY : 데이터베이스에 엔티티를 저장해서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- 객체 필드를 테이블 컬럼에 매핑
-
@Column
속성 정리
속성 | 기능 | 기본값 |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable, updatable | 등록, 변경 가능 여부 | TRUE |
nullable(DDL) | null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다. | |
unique(DDL) | @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다. | |
columnDefinition(DDL) | 데이터베이스 컬럼 정보를 직접 줄 수 있다. | |
length(DDL) | 문자 길이 제약조건, String 타입에만 사용한다. | 255 |
precision, scale(DDL) | BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다). precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다. |
precision=19, scale=2 |
-
@Column
생략- 자바의 기본 타입(int)에는 null 입력이 불가, 객체 타입(Integer)일때는 null 입력 허용
- JPA에서는 DDL 생성 기능을 사용시 기본 타입에 not null 제약 조건을 추가
-
@Column
사용시 nullable = true가 기본값임을 유의
- enum 타입 매핑에 사용
-
@Enumerated
사용 예- EnumType.ORDINAL(기본값) : enum에 정의된 순서대로 0부터 순서값을 저장
- 장점 : 데이터베이스에 저장되는 데이터 크기가 작다
- 단점 : 이미 저장된 enum의 순서를 변경할 수 없다
- EnumType.STRING : enum에 저장된 문자 그대로 데이터베이스에 저장
- 장점 : 저장된 enum의 순서가 바뀌거나 추가되어도 안전하다
- 단점 : 데이터베이스에 저장되는 데이터 크기가 ORDINAL에 비해서 크다
- EnumType.ORDINAL(기본값) : enum에 정의된 순서대로 0부터 순서값을 저장
- 날짜 타입(Date, Calendar)를 매핑할 때 사용한다.
-
@Temporal
사용 예- TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑(예: 2013–10–11)
- TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑(예: 11:11:11)
- TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑(예: 2013–10–11 11:11:11)
- 데이터베이스 BLOB, CLOB 타입과 매핑
-
@Lob
에는 지정할 수 있는 속성이 없다. - 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte[], java.sql.BLOB
- 이 필드는 매핑하지 않으며, 데이터베이스에 저장, 조회 하지 않음
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
- JPA가 엔티티 데이터에 접근하는 방식을 지정
-
@Access
사용 예- 필드 접근 : AccessType.FIELD, 필드 접근 권한이 private이어도 접근할 수 있다.
- 프로퍼티 접근 : AccessType.PROPERTY, 접근자(Getter)를 사용하여 접근
-
@Access
를 설정하지 않으면@Id
의 위치를 기준으로 접근 방식이 설정
- 객체 설계를 테이블 설계에 맞춘 방식
- 테이블의 외래키를 객체에 그대로 가져옴(Order.java의 memberId는 Member.java의 정보이지만 단순 memberId만 가져옴)
- 객체지향 설계 : 각각의 객체가 맡은 역할과 책임이 있고 관련 있는 객체끼리 참조하도록 설계해야 함