JPA & Querydsl/JPA

2. 엔티티 맵핑

1. 객체와 테이블 매핑

@Entity

 - @Entity가 붙은 클래스는 JPA가 관리하는 엔티티

 - 기본 생성자 필수 - (jpa에서 프록싱할때 사용하는 등에 필요)

 - final 클래스 enum, interface, inner 클래스는 사용이 불가능

 - 저장할 필드에 final 사용 불가능

 

@Table 

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

 - 속성 

    1) name: 매핑할 테이블 이름

    2) catalog: 데이터베이스 catalog 매핑

    3) schema: 데이터베이스 schema 매핑

    4) uniqueConstraints (DDL): DDL 생성 시에 유니크 제약 조건 생성

@Entity
@Table(name="Member")
public class Member2 { ~ }

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

- DDL을 애플리케이션 실행 시점에 자동 생성

- 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성

- 속성

  1) create: 기존테이블 삭제 후 다시 생성 (DROP + CREATE) 

  1) create-drop : create와 같으나 종료시점에 테이블 DROP

  1) update: 변경분만 반영

  1) validate: 엔티티와 테이블이 정상 매핑되었는지만 확인

  1) none: 사용하지 않음

(개발 초기 단계는 create 또는 update

테스트 서버는 update 또는 validate

스테이징과 운영 서버는 validate 또는 none)

<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

 

- 데이터베이스 방언 설정으로 다르게 셋팅 가능

<property name="hibernate.hbm2ddl.auto" value="create" />

- DDL 생성 기능(자동 생성할 때만 사용 되고 실행로직에는 영향 x)

//@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
@Column(name = "name")
private String username;

 

- 유니크 제약 조건 추가

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

 

필드와 컬럼 매핑

필드와 컬럼을 매핑에 사용하느 어노테이션 종류

 

@Column

//@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
@Column(name = "name")
private String username;

 

@Temporal

- 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용

( LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원))

@Temporal(TemporalType.TIMESTAMP)
private Date createDate;

@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;

// LocalDate, LocalDateTime 의 경우 자동 매핑됨
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;

 

@Enumerated

- 자바 enum 타입을 매핑할 때 사용

public enum RoleType {
    USER, ADMIN;
}
// @Enumerated(EnumType.ORDINAL) - enum 의 순서를 저장 : enum 순서가 바뀌면 문제 생김 사용 x
    @Enumerated(EnumType.STRING)
    private RoleType roleType;

 

@Lob

- 데이터베이스 BLOB, CLOB 타입과 매핑 

- @Lob에는 지정할 수 있는 속성이 없음

- 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑

CLOB: String, char[], java.sql.CLOB

BLOB: byte[], java.sql. BLOB 

@Transient
private int temp;

 

@Transient

- 필드 매핑X 

- 데이터베이스에 저장X, 조회X 

- 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용

@Transient
private Integer temp;

 

기본 키 매핑

기본 키 매핑 어노테이션

직접 할당: @Id만 사용

 

자동 생성(@GeneratedValue)

IDENTITY: 데이터베이스에 위임, MYSQL

SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용, ORACLE @SequenceGenerator 필요

TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용 @TableGenerator 필요

AUTO: 방언에 따라 자동 지정, 기본값

@Id
// @GeneratedValue(strategy = GenerationType.AUTO) // AUTO : DB에 위임
// @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY : MySQL auto_increment
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER2_SEQ_GENERATOR")  // SEQUENCE : Oracle 시퀀스 생성
private Long id;

 

 

실습 내용 전체 코드 

import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

@Entity
@SequenceGenerator(name="MEMBER2_SEQ_GENERATOR", sequenceName = "MEMBER_SEQ", initialValue = 1, allocationSize = 50)
public class Member2 {

    @Id
    // @GeneratedValue(strategy = GenerationType.AUTO) // AUTO : DB에 위임
    // @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY : MySQL auto_increment
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER2_SEQ_GENERATOR")  // SEQUENCE : Oracle 시퀀스 생성
    private Long id;

    //@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
    @Column(name = "name")
    private String username;

    //@Column(name = "age", updatable = false, insertable = false, nullable = false, unique = true)
    private Integer age;

    // @Enumerated(EnumType.ORDINAL) - enum 의 순서를 저장 : enum 순서가 바뀌면 문제 생김 사용 x
    @Enumerated(EnumType.STRING)
    private RoleType roleType;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;

    // LocalDate, LocalDateTime 의 경우 자동 매핑됨
    private LocalDate testLocalDate;
    private LocalDateTime testLocalDateTime;

    @Lob
    private String description;

    @Transient
    private int temp;

    public Member2() {}

    public Member2(Long id, String username, Integer age, RoleType roleType, Date createDate, Date lastModifiedDate, String description, int temp) {
        this.id = id;
        this.username = username;
        this.age = age;
        this.roleType = roleType;
        this.createDate = createDate;
        this.lastModifiedDate = lastModifiedDate;
        this.description = description;
        this.temp = temp;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public RoleType getRoleType() {
        return roleType;
    }

    public void setRoleType(RoleType roleType) {
        this.roleType = roleType;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public Date getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Date lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class MemberMappingTest {

    public static void main(String[] args) {
        // persistence.xml 의 persistence-unit 을 받아서 EntityManagerFactory 생성 - 하나만 생성해서 전체 어플리케이션 공유
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("test02");

        //EntityManagerFactory 에서 EntityManager 생성 - 쓰레드간에 공유 X (사용하고 버려야함)
        EntityManager em = emf.createEntityManager();

        // EntityManager 의 트랜잭션 받아옴
        EntityTransaction tx = em.getTransaction();

        // 트랜잭션 시작 - 모든 데이터 변경은 이 안에서 처리해야함
        tx.begin();

        try {
            /*
            // pk 전략이 IDENTITY 인 경우: 비영속 -> 영속이 되면 DB 에 Insert 를 하고 id 값을 가져옴
            // pk 전략이 SEQUENCE 인 경우: 비영속 -> 영속이 되면 SEQUENCE 에서 id 값(next value)을 가져옴
            Member2 member = new Member2();
            System.out.println("======= before =======");
            em.persist(member);
            System.out.println(member.getId());
            System.out.println("======= After =======");
            */

            /*
            // pk 전략이 SEQUENCE allocationSize 에 맞춰서 시퀀스를 미리 땡겨 옴
            Member2 member1 = new Member2();
            Member2 member2 = new Member2();
            Member2 member3 = new Member2();
            System.out.println("======= before =======");
            em.persist(member1);
            em.persist(member2);
            em.persist(member3);
            System.out.println(member1.getId());
            System.out.println(member2.getId());
            System.out.println(member3.getId());
            System.out.println("======= After =======");
            */


            // 트랜잭션 커밋
            tx.commit();
        } catch (Exception e){
            // 롤백
            tx.rollback();
        } finally {
            // EntityManager 닫음
            em.close();
        }

        // EntityManagerFactory 닫음
        emf.close();
    }

}

Reference

자바 ORM 표준 JPA 프로그래밍 - 김영한님

 

 

'JPA & Querydsl > JPA' 카테고리의 다른 글

5. 고급 매핑  (0) 2021.02.24
4. 다양한 연관관계 매핑  (0) 2021.02.24
3. 연관관계 매핑 기초  (0) 2021.02.22
1. 영속성 관리  (0) 2021.02.20
인텔리제이 자바 버전 변경  (0) 2021.02.16