본문 바로가기
[ ORM ]/JPA

[ JPA ] Entity Mapping

by 환이s 2024. 2. 26.


Entity Mapping

 

Entity Mapping객체와 데이터베이스 테이블 간의 매핑을 정의하는 작업을 말한다.

 

Java 언어로 정의된 Entity Class와 데이터베이스의 릴레이션(테이블) 간에 어떤 관계를 맺을지를 지정하는 것이며,

이를 통해 객체 지향 프로그래밍과 관계형 데이터베이스 간의 변화를 가능하게 한다.

 

Entity Mapping을 통해 Entity Class의 필드와 데이터베이스의 칼럼을 매핑하고,

객체 간의 관계를 데이터베이스의 외래 키(Foreign Key)와 연결하는데,

JPA를 사용하여 데이터베이스와 상호작용하는데 필요한 정보를 제공해 준다.

 

Entity Mapping은 아래와 같이 크게 4가지로 분류할 수 있다.

객체와 테이블 매핑: @Entity, @Table
기본 키 매핑: @Id
필드와 컬럼 매핑: @Column
연관관계 매핑: @ManyToOne, @JoinColumn, @OneToMany

 

특히 Entity 간의 연관 관계 매핑은 JPA에서 가장 어려우면서도 중요하다.

그래서 별도로 다음 포스팅에 더 자세하게 다룰 예정이다.

 

그럼 바로 3가지의 분류에 대해 더 자세히 알아보자.


객체와 테이블 매핑 - @Entity

 

@Entity 애노테이션을 클래스에 붙이면 해당 클래스가 JPA Entity임을 나타낸다.

 

JPA는 @Entity 애노테이션이 붙은 클래스를 데이터베이스의 테이블과

매핑하여 객체를 영구 저장소에 저장하고 관리한다.

@Entity
public class Member {
	...
}

 

JPA에서 관리하는 Entity Class는 반드시 @Entity 애노테이션이 붙어야 한다.

 

@Entity 애노테이션이 붙은 클래스는 JPA의 영속성 컨텍스트에서 관리되며,

데이터베이스와 매핑되는 역할을 수행한다.

 

또한 @Entity 애노테이션을 사용하는 클래스는 기본 생성자가 반드시 필요하고

파라미터가 없는 기본 생성자를 갖고 있어야 한다.

 

@Entity 애노테이션을 사용하여 JPA Entity Class를 정의하면,

JPA는 해당 클래스와 연결된 데이터베이스 테이블을 자동으로 생성하고,

Entity의 상태를 추적해서 영속성 컨텍스트를 통해 Entity를 관리하는 등의 기능을 제공한다.

 

  • 속성
    • name
      • JPA에서 사용할 Entity 이름을 지정한다.
      • 기본값 : 클래스 이름을 그대로 사용(예: Member)
      • 같은 클래스 이름이 없으면 가급적 기본 값을 사용한다.
@Entity(name="member")
public class Member {
	...
}

 

  • 주의
    • 기본 생성자 필수이다.
      • 파라미터가 없는 public 또는 protected 생성자
    • final 클래스, enum, interface, inner 클래스에 사용하지 않도록 주의하자.
    • 저장할 필드에 final을 사용하지 않는다.
hibernate는 클래스의 인스턴스를 생성할 때 reflection 기법을 사용하여 객체를 초기화해야 하기 때문에

만약 default 생성자가 존재하지 않으면 어떻게 초기화를 해야 할지 정하지 못하기 때문에
Entity 생성 시에는 반드시 기본 생성자가 있어야 한다.

기본적으로 별도의 생성자를 정의하지 않으면 자동으로 기본 생성자를 생성한다.

객체와 테이블 매핑 - @Table

 

@TableEntity와 매핑할 테이블을 지정한다.

 

@Entity
@Table(name = "MEMBER_INFO")
public class Member {
		...
}

 

위의 예시에서 @Table(name="MEMBER_INFO") 애노테이션은 Member 클래스를

데이터베이스의 MEMBER_INFO 테이블과 매핑하는 역할을 한다.

 

이렇게 테이블과 클래스를 매핑하면,

MEMBER 클래스의 인스턴스를 데이터베이스의 MEMBER_INFO 테이블과 연결하여

데이터를 주고받을 수 있다.

 

필드와 칼럼 매핑을 통해 JPA 클래스의 필드와 데이터베이스의 칼럼을 연결하여

데이터를 영속화하고 조회할 수 있으며, JPA의 기능과 편의성을 최대한 활용하여

데이터베이스와 자바 객체 간의 변환 작업을 간편하게 수행할 수 있다.

 

  • 속성
    • name
      • 매핑할 테이블 이름(Entity 이름을 사용)
    • catalog
      • catalog 기능이 있는 데이터베이스 catalog와 매핑한다.
      • 데이터베이스에는 여러 개의 카탈로그가 존재할 수 있으며, Entity가 속한 카탈로그를 지정할 때 사용한다.
    • schema
      • schema  기능이 있는 데이터베이스 schema와 매핑한다.
      • 스키마는 테이블의 집합을 그룹화하는 개념으로 사용되며, Entity가 속한 스키마를 지정할 때 사용한다.
    • uniqueConstraints(DDL)
      • DDL 생성 시에 유니크 제약 조건 생성한다.
        • 2개 이상의 복합 유니크 제약 조건도 만들 수 있다.
        • 참고로 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용한다.

 

  • 주의
    • @Table 애노테이션은 필수가 아니지만, @Entity 애노테이션과 @Id 애노테이션은 필수이다.
    • @Entity와 @Id는 함께 사용해야 한다.
    • @Id 애노테이션이 없으면 AnnotationException 예외가 발생한다.
    • 파라미터가 없는 기본 생성자는 필수로 추가해야 한다.

기본 키 매핑 - @Id

 

데이터베이스의 테이블에 기본 키 설정은 필수이다.

JPA에서는 기본적으로 @Id 애노테이션을 추가한 필드가 기본 키 칼럼이 된다.

 

[ JPA 기본 키 생성 전략 ]

  • 기본 키 직접 할당 : 애플리케이션 코드 상에서 기본 키를 직접 할당해 주는 방식이다.(@Id만 사용)
  • 기본 키 자동 생성
    • IDENTITY
      • 기본 키 생성을 데이터베이스에 위임하는 전략이다.
      • 데이터베이스에서 기본 키를 생성해 주는 대표적인 방식은 MySQL의 AUTO_INCREMENT 기능을 통해 자동 증가 숫자를 기본 키로 사용하는 방식이 있다.
    • SEQUENCE
      • 데이터베이스에서 제공하는 시퀀스를 사용해서 기본 키를 생성하는 전략이다.
    • TABLE
      • 별도의 키 생성 테이블을 사용하는 전략이다.

 

[ 기본 키 직접 할당 ]

 

기본 키를 직접 할당하는 경우 @Id만 사용한다.

 

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
/*
*   [@Entity]
*   -@Entity가 붙은 클래스는 JPA가 관리. Entity라 한다.
*   - JPA를 사용해서 테이블과 매핑할 클래스 @Entity 필수
*
*   <주의>
    - 기본 생성자 필수(파라미터가 없는 Public 또는 Protected 생성자)
    - final 클래스 , enum, interface, inner 클래스 사용 x
    - 저장할 필드에 final 사용 x

*   [@Entity 속성 정리]
*   - 속성 : name
*       -> JPA에서 사용할 엔티티 이름을 지정한다.
*       -> 기본값 : 클래스 이름을 그대로 사용(예 : Member)
*       -> 같은 클래스 이름이 없으면 가급적 기본값을 사용한다.
*
*   [@Table]
*   - @Table은 Entity와 매핑할 테이블 지정
*       - name : 매핑할 테이블 이름 -> 엔티티 이름을 사용
*       - catalog : 데이터베이스 catalog 매핑
*       - schema : 데이터베이스 schema 매핑
*       - uniqueConstraints(DDL) : DDL 생성 시에 유니크 제약 조건 생성
* */

@Entity //JPA가 관리할 객체
//@Table(name = "MBR")
//유니크 제약조건 추가
//DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
//@Table(uniqueConstraints = {@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"NAME" , "AGE"})})
public class Member {

    @Id // 데이터베이스 PK와 매핑
    private Long id;
    
    public Member(Long id) {
        this.id = id;
    }

 

Entity Class의 기본 키를 지정할 필드에 @Id 애노테이션을 붙이는 것으로 기본 키를 직접 할당할 수 있다.

 

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin(); //  트랜잭션 시작
        try{
            Member member = new Member();
            member.setId(1L);
            em.persist(member);
            tx.commit(); //  트랜잭션 커밋
        } catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

 

기본 키 직접 할당 이후 데이터를 저장할 수 있다.

 

[ IDENTITY 전략 ]

 

IDENTITY기본 키 생성하는 것을 데이터베이스에 위임하는 전략이다.

MySQL 데이터베이스에 사용하는 방식으로 AUTO_INCREMENT와 동일하다.

 

public class Member {

    @Id // 데이터베이스 PK와 매핑
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // IDENTITY
    private Long id;
    
    public Member(Long id) {
        this.id = id;
    }

 

IDENTITY 기본 키 생성 전략을 설정하기 위해

@GeneratedValue 애노테이션의 strategy 속성을 GenerationType.IDENTITY로 지정해야 한다.

 

이후 데이터베이스에서 기본 키를 대신 생성하게 된다.

 

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin(); //  트랜잭션 시작
        try{
            em.persist(new Member()); // 기본 키를 따로 지정하지 않고 저장
            Member member = em.find(Member.class, 1L); // id로 조회
            System.out.println("member id = " + member.getId());
            tx.commit(); //  트랜잭션 커밋
        } catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

 

해당 데이터를 저장할 때,

별도의 기본 키 값을 할당하지 않아도 데이터베이스에서

자동으로 기본 키를 할당하고 저장해 준다.

 

IDENTITY 전략은 기본 키 생성을 데이터베이스에 위임하기 때문에
데이터베이스에 저장이 되어야만 기본 키가 생성된다.

하지만, JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL을 실행하게 된다.
AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있다.

 

이러한 문제를 해결하기 위해 IDENTITY 전략에서는 persist()가 실행하는 시점에

즉시 INSERT SQL을 실행하고 DB에서 식별자를 조회하도록 하고 있다.

 

Member member = new Member();
member.setUsername("Hello");

System.out.println("member.getId() = " + member.getId());
em.persist(member);
System.out.println("member.getId() = " + member.getId());

tx.commit(); // COMMIT INSERT SQL 실행
// Query Result
...
member.getId() = null
Hibernate: 
    /* insert hellojpa.Member
        */ insert 
        into
            Member
            (id, name) 
        values
            (default, ?)
member.getId() = 1
...

 

 

 

[ SEQUENCE 전략 ]

 

SEQUENCE데이터베이스 시퀀스 오브젝트를 사용하여 기본 키를 자동으로 생성하는 전략이다.

Oracle 데이터베이스에서 사용하는 방식으로 생각하면 된다.

 

public class Member {

    @Id // 데이터베이스 PK와 매핑
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    
    public Member(Long id) {
        this.id = id;
    }

 

SEQUENCE 전략을 사용하기 위해서는 @GeneratedValue 애노테이션의 strategy 속성을

GenerationType.SEQUENCE로 지정해야 한다.

 

이는 데이터베이스 시퀀스를 사용하여 기본 키를 생성하게 된다.

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin(); //  트랜잭션 시작
        try{
            em.persist(new Member()); // 기본 키를 따로 지정하지 않고 저장
           
            Member member = em.find(Member.class, 1L); // id로 조회
            
            System.out.println("member id = " + member.getId());
            tx.commit(); //  트랜잭션 커밋
        } catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

 

IDENTITY 전략과 유사하게 기본 키를 지정하지 않고도 Member 객체를 생성하면서

Id를 통해 조회할 수 있다.

 

하지만 SEQUENCE 전략은 Entity가 영속성 컨텍스트에 저장되기 전에

데이터베이스 시퀀스에서 기본 키에 해당하는 값을 제공하게 된다.

 

또한 테이블마다 다른 시퀀스로 관리할 수 있게 해주는 애노테이션을 제공해 주는데

@SequenceGenerator를 통해 적용하면 된다.

 

@Entity
@SequenceGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        sequenceName = "MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
        initialValue = 1, allocationSize = 1)
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;

    public Member(Long id) {
        this.id = id;
}

 

  • 속성
    • name
      • 식별자 생성기 이름을 지정하는 것으로 필수로 작성해야 한다.
    • sequenceName
      • 데이터베이스에 등록되어 있는 시퀀스 이름을 지정한다.
      • 지정하지 않을 시 기본 값으로 hibernate_sequence라는 이름을 가지게 된다.
    • initalValue
      • DDL 생성 시에만 사용되는 속성이다.
      • 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정한다.
    • allocationSize
      • 시퀀스 한 번 호출에 증가하는 수를 지정하는 속성으로 기본 값은 50을 가진다.
      • 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다.
    • catalog, schema
      • 데이터베이스 catalog와 schema의 이름을 지정한다.
< 참고 >

SEQUENCE 전략은 데이터베이스의 시퀀스 오브젝트를 사용하기 때문에
데이터베이스로부터 시퀀스 값을 가져와야 한다.

따라서 SEQUENCE 전략은 persist() 실행 시
데이터베이스로부터 증가된 시퀀스 값을 가져올 수 있도록 쿼리문이 실행된다.

그 이후 commit이 실행되는 시점에 쿼리문을 보낸다.

 

member.setUsername("Hello");

System.out.println("member.getId() = " + member.getId());
em.persist(member); // 시퀀스 할당 시점
System.out.println("member.getId() = " + member.getId());

tx.commit(); // SQL 실행 시점

=============================================================
// 쿼리 생성 시점 출력
member.getId() = null
Hibernate: 
    call next value for MEMBER_SEQ // 시퀀스 증가 쿼리
member.getId() = 1

Hibernate: 
    /* insert hellojpa.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)

Process finished with exit code 0

 

persist()실행할 때마다 데이터베이스에 시퀀스 값을 증가시킬 경우 성능이 느려질 것이다.

이러한 문제를 해결하기 위한 속성이 allocationSize이다.

 

allocationSize는 데이터베이스의 시퀀스 사이즈를 미리 확보하여 메모리에 적재한다.

이후에는 persist()여러 번 호출되어도 데이터베이스에 쿼리문을 실행하는 것이 아닌,

메모리에서 시퀀스 값을 증가시키면서 가져올 수 있다.

 

allocationSize성능 최적화를 위해 사용하는 속성이다.

 

 

 

[ TABLE 전략 ]

 

테이블 전략은 키 생성 전용 테이블을 따로 만들어서 데이터베이스 시퀀스를 흉내 내는 전략이다.

모든 데이터베이스에 적용 가능하다는 장점이 있으나, 성능이 좋지 못하다.

 

@Entity
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        table = "MEMBER",
        pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
            
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;

    public Member(Long id) {
        this.id = id;
}

 

  • 속성
    • name
      • 식별자 생성기의 이름(필수 속성)
    • table
      • 키 생성 테이블의 이름(기본값 : hibernate_sequences)
    • pkColumnName
      • 시퀀스 칼럼의 이름(기본값 : sequence_name)
    • valueColumnNa
      • 시퀀스 값 칼럼명(기본값 : next_val)
    • pkColumnValue
      • key로 사용할 값 이름(기본값 : Entity Name)
    • initIalValue
      • 초기 값, 마지막으로 생성된 값이 기준이다.(기본값 : 0)
    • allocationSize
      • 시퀀스 한 번 호출에 증가하는 수 (기본값 : 50)
    • catalog, schema
      • 데이터베이스 catalog와 schema 이름
    • uniqueConstraints
      • 유니크 제약 조건 지정

 

[ AUTO 전략 ]

 

AUTO 전략은 @Id 필드에 @GeneratedValue(strategy = GenerationType.AUTO)를 지정하면서

JPA가 데이터베이스의 Dialect에 따라서 적절한 전략을 자동으로 선택하게 하는 방법이다.

 

@Entity
public class Member {
    @Id @GeneratedValue(strategy = GenerationType.AUTO) // 생략 가능하다.
    @Column(name = "MEMBER_ID")
    private Long id;
< 참고 > 

Dialect는 표준 SQL이 아닌 특정 데이터베이스에 특화된 고유한 기능을 의미한다.
만약, JPA가 지원하지 않는 데이터베이스의 기능을 사용할 경우 Dialect가 처리해 준다.

 

 

권장하는 식별자 전략

 

기본 키는 null 값을 가질 수 없어야 하며 유니크(유일한) 데이터이고 변하면 안 된다.

 

기본 키는 null 값을 가질 수 없으면서 유니크 값으로 제약하는 것은 쉽다. 

먼 미래까지 변하지 않고 유지하는 것은 어렵다.

 

하지만, 이 조건을 모두 만족하는 자연 키는 찾기 어렵다. 따라서 대리 키(대체키)를 사용해야 한다.

 

기본 키 제약 조건을 만족하기 위한 권장하는 방법은 기본키를 Long형 + 대체키 + 키 생성 전략을 사용하는 것이다.


필드와 칼럼 매핑 - @Column

 

필드와 칼럼 매핑은 JPA 클래스의 필드와 데이터베이스의 칼럼을 연결해 주는 작업이다.

이를 통해 JPA 클래스의 필드 값을 데이터베이스에 저장하고 조회할 수 있다.

 

JPA 클래스의 필드를 데이터베이스 칼럼과 연결한다.

필드의 타입과 이름, 접근 제어자 등을 이용하여 데이터베이스 칼럼과 매핑한다.

 

@Entity
public class Member {

@Id
@GeneratedValue
private Long id;

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

 

@Column(name="username') 애노테이션은 name 필드를 데이터베이스의 username 칼럼과 매핑하는 역할을 한다.

 

이렇게 필드와 칼럼을 매핑하면,

name 필드의 값을 데이터베이스의 username 칼럼에 저장하고 조회할 수 있다.

 

/*
*   [요구 사항 추가]
*   - 회원은 일반 회원과 관리자로 구분해야 한다.
*   - 회원 가입일과 수정일이 있어야 한다.
*   - 회원을 설명할 수 있는 필드가 있어야 한다.
*   - 이 필드는 길이 제한이 없다.
* */
/*
*   [@Column]
*
*   name = 필드와 매핑할 테이블의 컬럼 이름 -> 객체의 필드 이름
*   insertable,updatable = 등록, 변경 가능 여부 -> TRUE
*   nullable(DDL) = null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.
*   unique(DDL) = @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
*   columnDefinition(DDL) = 데이터베이스 컬럼 정보를 직접 줄 수 있다.
*       -> ex) varchar(100) default 'EMPTY' -> 필드의 자바 타입과 방언 정보를 사용함.
*   length(DDL) = 문자 길이 제약조건, String 타입에만 사용한다. -> 255
*
*   precision,scale(DDL) = BigDecimal 타입에서 사용한다.(BigInteger도 사용할 수 있다.).
*                          precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수다.
*                          참고로 double, float 타입에는 적용되지 않는다.
*                          아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다.
*                   -> precision = 19, scale =2
*
* */

//@Entity //JPA가 관리할 객체
public class MemberColumn {

    @Id
    private Long id;
    @Column(name = "name") // 컬럼 매핑
    private String username;
    private Integer age;
    @Enumerated(EnumType.STRING) // enum 타입 매핑
    private RoleType roleType;
    /*
    *   [@Enumerated]
    *   자바 enum 타입을 매핑할 때 사용한다.
    *   주의 사항으로 ORDINAL 사용 x
    *
    *   value = EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
    *           EnumType.STRING : enum 이름을 데이터베이스에 저장
    *           -> EnumType.ORDINAL (기본값)
    *
    * */
    @Temporal(TemporalType.TIMESTAMP) // 날짜 타입 매핑
    private Date createDate;


    @Temporal(TemporalType.TIMESTAMP) // 날짜 타입 매핑
    private Date lastModifiedDate;

    private LocalDate testLocalDate;
    private LocalDateTime testLocalDateTime;

    /*
    *   [@Temporal]
    *   날짜 타입을 매핑할 때 사용
    *   (지금은 사실 필요 없다.)
    *   참고로 LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원)
    *
    * • TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑
        (예: 2013–10–11)
        • TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑
        (예: 11:11:11)
        • TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이 스
        timestamp 타입과 매핑(예: 2013–10–11 11:11:11)
    * */
    @Lob // BLOB, CLOB 매핑
    private String description;
    /*  [@Lob]
    *   @Lob에는 지정할 수 있는 속성이 없다.
    *   매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
    *
    *   CLOB : String , char[], java.sql.CLOB
    *   BLOB : byte[], java.sql.BLOB
    * */

//    @Transient : 특정 필드를 컬럼에 매핑하지 않음(매핑 무시)
//                 필드 매핑 x , 데이터베이스에 저장x, 조회 x
//                 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용

 


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

 

DataBase Schema 자동 생성은 JPA를 사용할 때 제공되는 기능 중 하나이다.

 

JPA는 객체와 데이터베이스 테이블을 매핑하기 위해 사용되는 ORM 기술로,

Entity Class를 바탕으로 데이터베이스 테이블을 자동으로 생성할 수 있다.

 

Spring FrameWork를 사용하는 경우,

Spring Boot를 통해 JPA 설정을 간단하게 구성할 수 있으며, 스키마 자동 생성을 활성화할 수 있다.

 

스키마 자동 생성은 주로 개발 환경에서 사용되고, DDL 생성 기능은

DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.

 

Spring Boot를 사용하여 데이터베이스 스키마 자동 생성을 활성화려면

application.properties 또는 yml 파일에 다음과 같이 설정하면 된다.

 

# application.properties -> 스키마 자동 생성
spring.jpa.hibernate.ddl-auto=create

# application.properties -> 스키마 자동 생성을 비활성화
spring.jpa.hibernate.ddl-auto=none

 

XML 설정은 다음과 같이 설정하면 된다.

 

 <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 -->
            <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="sa"/>
            <property name="jakarta.persistence.jdbc.password" value=""/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments"  value="true"/>
            <property name="hibernate.jdbc.batch_size" value="10"/> <!-- 설정 시 사이즈만큼 모아서 DB에 한꺼번에 쿼리를 보내고 DB를 커밋한다.(버퍼링 기능)  -->
            <property name="hibernate.hbm2ddl.auto" value="create" /><!--기존 테이블 삭제 후 다시 생성 (DROP + CREATE)-->
            <!--<property name="hibernate.hbm2ddl.auto" value="create-drop" />--><!--create와 같으나 종료 시점에 테이블 DROP-->
            <!--<property name="hibernate.hbm2ddl.auto" value="update" />--><!--변경분만 반영 (운영DB에는 사용하면 안됨)-->
            <!--<property name="hibernate.hbm2ddl.auto" value="validate" />--><!--엔티티와 테이블이 정상 매핑되었는지만 확인-->
            <!--<property name="hibernate.hbm2ddl.auto" value="none" />--><!--사용하지 않음-->
        </properties>
    </persistence-unit>
    <!--
   -> hibernate.dialect 속성에 지정
    • H2 : org.hibernate.dialect.H2Dialect
    • Oracle 10g : org.hibernate.dialect.Oracle10gDialect
    • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
    • 하이버네이트는 40가지 이상의 데이터베이스 방언 지원

    -->
    <!--
    [ 데이터베이스 스키마 자동 생성 ]
    - DDL을 애플리케이션 실행 시점에 자동 생성
    - 테이블 중심 -> 객체 중심
    - 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
    - 이렇게 생성된 DDL은 개발 장비에서만 사용 !!!!!!!!!!!!!!!!!!
    - 생성된 DDL은 운영 서버에서는 사용하지 않거나, 적절히 다듬은 후 사용

    [ 데이터베이스 스키마 자동 생성 -주의 ]
    - 운영 장비에는 절대 create, create-drop , update 사용하면 안된다.
    - 개발 초기 단계는 create 또는 update
    - 테스트 서버는 update 또는 validate
    - 스테이징과 운영 서버는 validate 또는 none
    -->

 

위의 설정은 애플리케이션을 실행할 때마다

Entity Class를 기반으로 데이터베이스에 테이블을 자동으로 생성한다.

 

그러나 스키마 자동 생성을 사용할 때는 주의해야 한다.

 

이미 데이터베이스에 데이터가 존재하는 경우,

스키마 자동 생성 시 기존 데이터가 삭제될 수 있으므로,

테스트 환경 등 개발 시에만 사용하는 것이 좋다.

 

  • 속성
    • create
      • 애플리케이션 시작 시 스키마를 생성한다.
      • 이미 존재하는 경우 삭제하고 다시 생성한다.(개발 초기 단계에는 create, update)
    • update
      • 변경된 부분만 반영해 주고, 운영 DB에는 절대 사용하면 안 된다.
    • drop
      • 애플리케이션 종료 시 스키마를 삭제한다.
    • none
      • 개발자가 수동으로 스키마를 생성한다.
    • validate
      • Entity와 테이블이 정상 매핑되었는지 확인할 때 사용한다.

마치며

 

오늘은 Entity Mapping Section에 대해 알아봤습니다.

다음 포스팅에서 뵙겠습니다.

 

위 포스팅 글은 김영한님의 자바 ORM 표준 JPA 프로그래밍-기본편을 참고했습니다.

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 - 인프런

회사땜에 매일 바쁜 와중에 학원이라도 다닐까 생각했는데 마침 JPA 강의가 생겨서 꿀 타이밍이네요. 저는 이 전에 JPA 책을 보고 공부 했었는데요 궁금했던 점, 업무에 적용하며 고민하고 해결하

www.inflearn.com

 

728x90