@Entity
@Entity가 붙은 클래스는 JPA가 관리하는 엔티티라 한다.
JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 가 필수임
※ 주의사항
- 기본 생성자 필수 (파라미터가 없는 public 또는 protected 생성자)
- final 클래스 , enum , interface , inner 클래스는 사용하면 안됨
- 저장할 필드에 final 사용하면 안됨
속성 :
@Table(Name ="MEMBER") : JPA에서 사용할 엔티티 이름을 지정한다.
기본값 : 클래스 이름을 그대로 사용(예:Member)
같은 클래스 이름이 없으면 가급적 기본값을 사용한다.
catalog : 데이터베이스 catalog 매핑
schema : 데이터베이스 schema 매핑
uniqueConstraints(DDL) : DDL 생성 시에 유니크 제약조건 생성
- DDL을 어플리케이션 실행 시점에 자동 생성
- 테이블 중심 -> 객체 중심
- 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
- 이렇게 생성된 DDL은 개발 장비에서만 사용
- 생성된 DDL은 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용
속성 :
아래와 같이 사용함
<property name="hibernate.hbm2ddl.auto" value="validate"/>
create : 기존테이블 삭제 후 다시 생성 (DROP+CREATE)
create-drop : CREATE 와 같으나 종료 시점에 테이블 DROP
update : 변경분만 반영 (운영DB에는 사용하면 안됨)
alter table 쿼리문을 생성함, 지우는것은 안되며 추가만 가능
validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
none : 사용하지 않음, 관례상 사용함
※ 주의사항
- 운영 장비에서는 절대 create , create-drop , update 사용하면 안됨
- 개발 초기 단계에는 create 또는 update
- 테스트 서버는 update 또는 validate
- 스테이징과 운영 서버는 validate 또는 none
왠만하면 본인이 직접 테이블 생성 쿼리를 작성해서 DBA 에게 전달.
DDL 생성 기능 :
- 제약 조건 추가
@Cloumn(unique=true, length =10, name= "USERNAME")
- 유니크 제약 조건 추가
@Table(uniqueConstraints = {@UniqueConstraint(name ="NAME_AGE_UNIQUE", columnNames{"NAME","AGE})}
DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않음
@Column : 컬럼 매핑
name : 필드와 매핑할 테이블의 컬럼 이름 (default : 객체의 필드 이름)
insertable , updatable : 등록 변경 가능 여부 (default : TRUE)
nullable(DDL) : null 값의 허용 여부를 설정함, false로 설정하면 DDL 생성시에 not null 제약조건이 붙는다.
unique(DDL) : @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 떄 사용함
이름을 알아볼수 없게 나옴, 그래서 잘 안씀 @Table에서 사용하는것을 선호함
columnDefinition(DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있다.
ex) varchar(100) default 'EMPTY'
length(DDL) : 문자 길이 제약 조건 , String 타입에만 사용함 (default : 255)
precision , scale(DDL) : BigDecimal 타입에 사용함(BigInteger도 사용가능)
precision은 소수점을 포함한 전체 자릿수를 scale은 소수즤 자릿수임.
참고로 double ,float 타입에는 적용되지 않음
정밀한 소수를 다루어야 할때만 사용함
@Temporal : 날짜 타입 매핑
TemporalType.DATE
TemporalType.TIME
TemporalType.TIMESTAMP
LocalDate , LocalDateTime 사용시에는 생략이 가능함 (최신 하이버네이트 지원)
LocalDate는 date로 지정됨
LocalDateTime은 timstamp로 지정됨
@Enumerated : enum 타입 매핑, 해당 어노테이션 사용시 EnumType.STRING을 무조건 지정
EnumType.STRING : enum 이름을 데이터 베이스에 저장,
EnumType.ORDINAL : enum 순서를 데이터베이스에 저장, 쓰지말자
defalut : EnumType.ORDINAL
※ EnumType.ORDINAL 는 사용하면 안됨, 순서로 들어감
요구사항이 추가되어서 enum 타입이 추가되면 순서가 꼬임, 지옥감
@Lob : 지정할수 있는 속성이 없음
문자면 CLOB 매핑 (String , char[] , java,sql.CLOB)
나머지는 BLOB 매핑 (byte[] , java.sql.BLOB)
@Transient : 특정 필드를 컬럼에 매핑하고 싶지 않을때
직접 할당 : @Id
자동 생성 : @GeneratedValue
IDENTITY : 데이터베이스에 위임 , MYSQL
기본키 생성을 데이터베이스에 위임
@GeneratedValue(strategy = GenerationType.IDENTITY)
- 주로 MySQL , PostgreSQL , SQL Server , DB2에서 사용
(MySQL의 AUTO_INCREMENT)
-JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
-AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
-IDENTITY 전략은 em.persist()시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회
특징 :
DB에 들어가야 ID 값을 알 수 있음
그래서 얘는 em.persist 하는시점에 데이터베이스에 쿼리를 날림
SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용 , ORACLE
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@SequenceGenerator 필요, 시퀀스제네레이터는 클래스 위에 붙임
- 사용 가능 속성
name : 식별자 생성기 이름
sequenceName : 데이터베이스에 등록되어 있는 시퀀스 이름
initialValue : DDL 생성 시에만 사용되며, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수로 지정
allocationSize : 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨)
데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값은 반드시 1로 설정해야 함 (기본값 50)
catalog , schema : 데이터베이스catalog , schema 이름
=====================================================================
@SequenceGenerator(name="member_seq_generator" , sequenceName = "member_seq")
public class Member {
@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "member_seq_generator")
private Long id;
=====================================================================
특징 :
DB에서 시퀀스를 먼저 조회해 온뒤 영속성 컨텍스트에 추가 후 나중에 커밋하는 시점에 쿼리를 날림
TABLE : 키 생성용 테이블 사용 , 모든 DB에서 사용
@GeneratedValue(strategy = GenerationType.TABLE)
@TableGenerator 필요 , 클래스 위에붙임
키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
장점 : 모든 데이터베이스에 적용 가능
단점 : 성능
- 사용 가능 속성
name : 식별자 생성기 이름
table : 키생성 테이블명 (hibernate_sequences)
pkColumnName : 시퀀스 컬럼명 (sequence_name)
valueColumnNa : 시퀀스 값 컬럼명 (next_val)
pkColumnValue : 키로 사용할 값 이름 (엔티티 이름)
initialValue : 초기 값, 마지막으로 생성된 갓이 기준 (기본값 0)
allocationSize : 시퀀스 한번에 호출하는 수 (기본값 50)
catalog, schema : 데이터베이스 catalog , schema 이름
uniqueConstraints(DDL) : 유니크 제약 조건
=====================================================================
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "MEMBER_SEQ", allocationSize = 1
)
public class Member {
=====================================================================
AUTO : 방언에 따라 자동 지정
@GeneratedValue(strategy = GenerationType.AUTO)
- 기본 키 제약 조건: null아님, 유일 , 변하면 안된다
- 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
- 예를 들어 주민등록번호도 기본 키로 적절하지 않다.
권장 : Long형 + 대체키 + 키 생성전략 사용
- 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
- 테이블의 외래키를 객체에 그대로 가져옴
- 객체 그래프 탐색이 불가능
- 참조가 없으므로 UML도 잘못됨