JPA

JPA기본편 - 엔티티 매핑 (객체와 테이블, 필드와 컬럼, 기본 키 매핑)

땅콩콩 2023. 4. 1. 13:55
데이터베이스 스키마 자동 생성

jpa에서는 DDL을 애플리케이션 실행 시점에 자동으로 생성해준다.

데이터베이스 방언(dialect)을 이용해서 데이터베이스에 맞는 적절한 DDL을 생성한다.

그리고 이렇게 생성된 DDL은 개발 장비에서만 사용하고 운영서버에서는 사용하지 않는다. (사용하더라도 다듬고 사용)

 

hibernate.hbm2ddl.auto 옵션

create 기존 테이블 삭제 후 다시 생성 (drop + create)
create-drop create와 같으나 종료 시점에 테이블 drop
update 변경분만 반영(운영 DB에는 사용하면 안됨!)
validate 엔티티와 테이블이 정상 매핑되었는지만 확인
none 사용하지 않음.

 

운영장비에는 절대 create, create-drop, update를 사용하면 안된다! (실행할때마다 데이터가 날아감)
개발 초기단계에는 create, update로, 테스트 서버는 update또는 validate로 사용해도
스테이징/운영서버는 validate또는 none으로 사용하는 것이 좋다.

또한 DDL생성기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다. (데이터베이스에만 영향을 줌)

 

 

엔티티 매핑 소개

1. 객체와 테이블 매핑 : @Entity, @Table

2. 필드와 컬럼 매핑 : @Column

3. 기본 키 매핑 : @Id

4. 연관관계 매핑 : @ManyToOne, @JoinColumn 등

 

 

객체와 테이블 매핑

1. @Entity

@Entity가 붙은 클래스는 JPA가 관리하는 엔티티가 된다.

따라서 JPA를 사용해서 테이블과 매핑할 클래스는 @Entity가 필수이다.

- 기본 생성자 필수 (파라미터가 없는 public/protected 생성자)
- final, enum, interface, inner클래스는 사용 불가
- 저장할 필드에 final 사용 불가

@Entity의 name 속성은 Jpa에서 사용할 엔티티 이름을 지정한다.

@Entity(name="Member")

기본값은 클래스 이름을 그대로 사용하는데, 중복되는 클래스 이름이 없으면 가급적 기본값을 사용한다.

 

2. @Table

@Table은 엔티티와 매핑할 테이블을 지정한다.

@Table(name="MBR") //매핑할 테이블 이름 지정. 기본값은 엔티티 이름으로 사용.
@Table(catalog= ) //데이터베이스 catalog 매핑
@Table(schema= ) //데이터베이스 schema 매핑
@Table(uniqueConstraint= ) //DDL생성시 유니크 제약조건 생성.

 

 

필드와 컬럼 매핑
@Column 컬럼 매핑
@Temporal 날짜 타입 매핑
@Enumerated enum타입 매핑
@Lob BLOB, CLOB 매핑
@Transient 특정 필드를 컬럼에 매핑x (매핑 무시하고 DB에 반영하지 않음)
@Id //데이터베이스 pk와 매핑
private Long id;

@Column(name = "name") //객체에서는 username, DB에서는 컬럼명을 name으로 쓰고싶을때
private String username;

private Integer age;

@Enumerated(EnumType.STRING) //객체에서 ENUM 타입 쓰고싶을 떄.
private RoleType roleType;

//객체에서 날짜 타입 쓰고싶을 때. DATE(날짜), TIME(시간), TIMESTAMP(날짜+시간)
//LocalDate, LocalDateTime사용시 생략 가능
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;

private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;

@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;

@Lob //varchar를 넘어서는 큰 값을 넣고싶을 떄.
private String description;

@Transient //db에 매핑하고싶지 않을 때.
private int temp;

 

1. @Column

속성 설명 기본값
name 필드와 매핑할 테이블의 컬럼 이름 객체의 필드 이름
insertable, updatable 등록, 변경 가능 여부 TRUE
nullable (DDL) null값 허용여부. false하면 not null 추가됨  
unique (DDL) 유니크 제약조건. 근데 잘 쓰지 않고 @Table(uniqueConstraint=true) 사용  
columnDefinition (DDL) 데이터베이스 컬럼정보를 직접 줄때 사용 필드의 자바 타입, 방언정보 사용
length (DDL) 문자길이 제약 조건. String 타입에만 사용 255
precision, scale (DDL) BigDecimal 타입에서 사용 (BigInteger도 사용할 수 있다). precision=19, scale=2

 

2. @Enumerated <주의>

@Enumerated(EnumType.ORDINARY) 사용하지 말것!!

enum타입에 값이 추가되면 인덱스가 밀려서 DB운영에 굉장히 위험하다..

@Enumerated(EnumType.STRING)을 사용하자.  

 

3. @Lob

지정할 수 있는 속성이 따로 없고, 매핑하는 속성이 문자면 CLOB 나머지는 BLOB 매핑.

 

 

기본 키 매핑

기본 키 매핑 애노테이션에는 @Id, @GeneratedValue 가 있다.

@Id //기본키 직접 할당
@GeneratedValue(strategy = ??) //기본키 자동생성
private Long id;

@Id는 기본키를 직접 할당하고,

@GeneratedValue는 strategy에 따라서 다양한 방법으로 기본키를 자동 생성한다.

이 @GeneratedValue의 strategy 옵션은 다음과 같다. (옵션을 생략하면 AUTO)

 

 

1. IDENTITY = 데이터베이스에 위임(mysql)

2. SEQUENCE = 데이터베이스 시퀀스 오브젝트 사용(oracle), @SequenceGenerator 필요

3. TABLE = 키 생성용 테이블 사용(모든 db에서 사용), @TableGenerator 필요

4. AUTO = 방언에 따라 자동 지정, 기본값

 

 

좀 더 자세히 살펴보자.

 

1. IDENTITY 전략

@Entity
public class Member {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
}

기본키 생성을 데이터베이스에 위임하는 전략이며 주로 mysql, postgre sql, sql server, db2에서 사용한다.

 

[주의]

JPA는 보통 트랜잭션 커밋 시점에 insert sql을 실행한다. 그런데 AUTO_INCREMENT는 데이터베이스에 insert sql을 실행한 이후에 ID값을 알 수 있다.

그래서 IDENTITY전략에서는 sql실행을 commit()시점까지 미루지 않고 em.persist()시점에 바로 실행한다.

그리고 DB에서 식별자를 조회하게 된다. 

 

 

2. SEQUENCE 전략

@Entity
@SequenceGenerator(
        name = "MEMBER_SEQ_GENERATOR", //시퀀스 generator 이름
        sequenceName = "MEMBER_SEQ", //데이터베이스에 등록된 시퀀스 이름
        initialValue = 1, allocationSize = 50) //next call할때 시퀀스값을 50개씩 미리 만들어놓고, 메모리에서 가져다 쓴다.
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
}

데이터베이스 시퀀스를 사용하는 전략이며, oracle, postgre sql, db2, h2 database에서 사용한다.

여기서 데이터베이스 시퀀스란, 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다. (ex, 오라클 시퀀스)

 

 

3. TABLE 전략

@Entity
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR", //generator이름
        table = "MY_SEQUENCES", //키를 생성하는 테이블 이름
        pkColumnValue = "MEMBER_SEQ", allocationSize = 50) //시퀀스 한번 호출에 증가하는 수
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
}

키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이며, 모든 데이터베이스에 사용 가능하다.

하지만 성능측면에서 떨어진다는 단점이 있다.

권장하는 식별자 전략

기본키 제약조건 : null아님 + 유일 + 불변
권장 : Long형 + 대체키 + 키 생성전략 사용

 

*인프런 김영한님의 JPA 기본편 강의를 들으며 정리한 내용입니다.

*https://www.inflearn.com/course/ORM-JPA-Basic