3

yeoro·2021년 9월 17일
0

엔티티 매핑

객체 - 테이블

@Entity

  • @Entity가 붙은 클래스는 JPA가 관리한다. 따라서 JPA를 사용할 테이블과 매핑할 클래스는 필수로 사용해야 한다.
  • 기본 생성자 필수 (public, protected)
  • final(필드, 클래스), enum, interface, inner class X

name

  • JPA에서 사용하고 구분할 엔티티 이름
  • 가급적으로 기본값을 사용한다 (클래스 이름)

@Table

  • 엔티티와 매핑할 테이블 지정

name

  • 매핑할 테이블 이름

catalog

  • 데이터베이스 catalog 매핑

schema

  • 데이터베이스 schema 매핑

uniqueConstraints(DDL)

  • DDL 생성 시에 유니크 제약 조건 생성

데이터베이스 스키마 자동 생성

  • DDL을 애플리케이션 실행 시점에 자동 생성
  • 테이블 중심이 아닌 객체 중심
  • 생성된 DDL은 운영서버가 아닌 개발서버에서 사용
  • 데이터베이스에 맞는 적절한 DDL 생성 오라클의 경우 varchar2, mysql은 varchar

속성

hibernate.hdm2ddl.auto

  • create : 기존테이블 삭제 후 다시 생성 (DROP + CREATE)
  • create-drop : create와 같지만 종료시점에 테이블 DROP (Test Case 사용시)
  • update : 변경된 부분만 반영 (운영DB 사용X)
  • validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
  • none : 기능 사용 안 함

주의

운영 장비에는 절대 create, create-drop, update 사용 금지, 보통 WAS 계정을 나누어 운영

  • 개발 초기 단계는 create, update
  • 테스트 서버는 update, validate (여러 명이 사용하는 서버)
  • 스테이징과 운영 서버는 validate, none

DDL 생성 기능

제약조건 추가 - @Column

@Column(nullable = false, length = 10)
회원 이름 필수, 10자 이하

유니크 제약조건 추가

@Table(uniqueConstraints = {@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"})})

DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직(런타임)에는 영향을 주지 않는다.


필드 - 컬럼

private Integer age;

DB에서 Integer와 맞는 적절한 타입 설정

@Column

name

@Column(name = "name")
private String username;

DB컬럼명은 name, 변수명은 username

  • 필드와 매핑할 테이블의 컬럼 이름 (기본값 : 객체의 필드 이름)

insertable, updatable

  • 등록, 변경 가능 여부

nullable

  • null 값의 허용 여부 설정. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.

unique

  • @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약 조건을 걸 때 사용
  • 제약조건 이름이 랜덤으로 나오므로 알아보기 힘들기 때문에 보통 @Table을 사용한다.

columnDefinition

  • 데이터 베이스 컬럼 정보를 직접 줄 수 있다.
  • varchar(100) default 'EMPTY' 와 같이 직접 작성 가능

precision, scale

  • BigDecimal, BigInteger에 사용
  • precision : 소수점을 포함한 전체 자릿수
  • scale : 소수외 자리수
  • double, float 적용 안 됨

@Enumerated

@Enumerated(EnumType.STRING)
private ROleType roleType;

DB에서는 ENUM 타입이 존재하지 않기 때문에 선언해주어야 함

value

  • ORDINAL : enum 순서(0부터) 저장 -> enum이 수정되어 순서가 바뀌면 뒤죽박죽 돼서 절대 쓰지 말것
  • STRING : enum 이름 저장

@Temporal

@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;

JAVA의 datetime은 날짜+시간, DB는 날짜, 시간, 날짜+시간이기 때문에 매핑 정보를 주어야 함

  • 날짜 타입을 매핑할 때 사용
  • 현재는 아래와 같이 데이터타입만으로 가능해짐
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;
  • localDate : 년, 월
  • localDateTime : 년, 월, 일

@Lob

@Lob
private String description;
  • 큰 내용을 넣을 때
  • DB의 BLOB, CLOB 타입과 매핑
  • 지정할 수 있는 속성이 없다.
  • CLOB : String, char[]
  • BLOB : byte[]

@Transient

@Transient
private int temp;
  • 컬럼에 생성하지 않으려고 할 때, DB와 매핑하지 않을 때

기본 키 매핑

@Id

@Id
private String id;
  • 직접 id를 만들어서 사용

@GeneratedValue

@ID
@GeneratedValue
private Long id;
  • 자동으로 id 생성

IDENTITY 전략

strategy = GenerationType.IDENTITY

  • 기본 키 생성을 DB에 위임
  • 주로 MySQL(AUTO_INCREMENT), PostgreSQL, SQL Server 등에서 사용
  1. id에 값을 넣지 않고 DB에 insert
  2. DB에 들어왔을 때 id값이 생성 - 이 때 id값을 알 수 있음
  3. 영속성 컨텍스트에 넣으려면 pk 값이 있어야하는데, DB에 들어가야 알 수 있는 문제 발생
  4. 이러한 문제를 해결하기 위해 울며 겨자먹기.. 로 트랜잭션이 커밋되는 시점이 아닌 그 전에 바로 쿼리를 실행하여 id 값을 만들고 가져온다.
  5. 한 트랜잭션 안에서 이와 같은 쿼리를 많이 날려도 성능에 차이가 별로 없다.

SEQUENCE 전략

strategy = GenerationType.SEQUENCE

  • 사용자 지정
@SequenceGenerator(name = "CUSTOM_SEQ_GENERATOR")
public class Member {
 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE)
}
  1. 시퀀스 또한 DB에 넣을 때 값을 알 수 있어서 가져와야한다.
  2. 영속성 컨텍스트에 넣으려면 pk가 필요해서 시퀀스를 가져와야 한다.
  3. 시퀀스 테이블에서 해당 시퀀스의 현재 값을 보고 다음 값을 가져온다.
  4. 시퀀스 테이블에 이전값이 있기 때문에 쿼리를 먼저 실행할 필요 없이 시퀀스 테이블만 참조하면 된다.
  5. 테이블을 여러번 조회해야 하기 때문에 성능이 안 좋을 수 있는데, allocationSize 속성을 통해 미리 시퀀스를 가져오며 해결할 수 있다.

TABLE 전략

  • 키 생성 전용 테이블을 하나 만들어서 DB 시퀀스를 흉내내는 전략
  • 장점 : 모든 DB에 적용 가능
  • 단점 : 테이블을 직접 사용하여 락이 걸리거나 최적화가 되어있지 않기 때문에 성능이 안 좋음
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 {}

권장 식별자 전략

  • 기본 키는 not null, 변하면 안 된다.
  • 미래까지 이 조건을 만족하는 자연키는 찾기 힘들다. 대리키(대체키)를 사용한다. ex) 주민번호도 기본 키로 적절하지 않음
  • Long 타입 + 대체키 + 키 생성전략
  • 비즈니스를 키로 가져오는 것은 권장하지 않는다.

0개의 댓글