[JAVA] JPA 기본설정 및 객체생성(2)

About JPA annotaion

Posted by JongMin-Lee on February 9, 2020

관련된 글

  1. [JAVA] JPA(Java Persistence API)란?(1)
  2. [JAVA] JPA 기본설정 및 객체생성(2)
  3. [JAVA] JPA 어노테이션 및 트랜잭션(3)
  4. [JAVA] JPA 연관관계(4)
  5. [JAVA] JPA 영속성 컨텍스트(5)

1. 시작하기(환경설정)

이번 시간부터 실습을 통해서 JPA에 대해 알아보겠습니다.
실습환경은 다음과 같습니다.

  1. java 1.8
  2. Spring Boot 2.2.4.RELEASE
  3. H2 DataBase

    H2 DataBase는 In-Memory형식으로 Test및 개발시 많이 사용하게 됩니다.(운영에서는 사용X)

  4. maven

maven-dependency

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.3.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

기본 Spring boot project에서 webH2 데이터베이스와 Hibernate만 추가하였습니다.

Hibernate는 JPA와 같이 ORM 라이브러리중 하나입니다.
Hibernate는 쉽게 말해 JPA의 구현체?라고 생각합니다.

Maven 의존성을 추가했다면 데이터베이스 설정을 해줍니다.

resource/META-INF/persistence.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">

    <persistence-unit name="jongmin">
        <properties>

            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/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.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>

</persistence>

먼저 H2 데이터베이스에 대한 설정을 진행합니다. 설정은 Spring boot H2 설정을 참고했습니다. 그 다음으로 h2-console을 사용하기 위해 추가적인 설정을 진행했습니다. application.properties파일에 다음과 같은 설정을 추가했습니다.

1
2
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

다른 사람들은 안하는 경우도 있었는데 저는 이 설정을 추가하지 않으면 h2-console에 접근이 안됬습니다…
h2 console은 기본적으로 false처리 되어 있습니다. 따라서 true로 지정해주고 path를 지정했습니다.
접속은 http://localhost:8080/h2-console로 할 수 있습니다.

마지막으로 hibernate.hbm2ddl.auto입니다. 이 설정은 데이터베이스 스키마에 대한 설정입니다.
이 설정에 대한 특징은 다음과 같습니다.

  • DDL을 애플리케이션 실행시점에 자동으로 생성
  • 테이블중심 -> 객체중심
  • 데이터베이스 Dialect를 활용하여 적절한 DDL 생성
  • 이렇게 생성된 DDL은 개발 장비에서만 사용
  • 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용

DDL 설정값은 다음과 같습니다.

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

주의사항

  • 운영장비에서는 절대 create,create-drop,update를 사용하면 안된다.
  • 개발초기단계는 create 또는 update
  • 테스트서버는 update 또는 validate
  • 스테이징과 운영서버는 validate 또는 none

설정은 여기에서 마치고 객체를 만들도록 하겠습니다.

2. 객체 생성(Entity)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Entity
public class Member {

    @Id
    @GeneratedValue
    Long id;

    String name;
    int age;

// getter, setter...
}

@Entity
public class Club {

    @Id
    @GeneratedValue
    Long id;

    String clubName;

// getter, setter...
}

먼저 위의 어노테이션에 대해 알아보겠습니다.

@Entity

해당 Class가 JPA에 의해 관리되는 Entity라고 설정해주는 것입니다.

@Id

데이터베이스의 Primary Key(기본키)와 매핑해주는 역할을 합니다.

@GeneratedValue

기본키를 만들어 주는 역할을 합니다. 이 어노테이션에는 strategy(전략)가 존재합니다.
다음과 같이 사용이 가능합니다. @GeneratedValue(strategy = GenerationType.AUTO)
이 strategy의 속성을 살펴보겠습니다.

  • IDENTITY : 데이터베이스에 위임한다.(Mysql)
  • SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용.(Oracle),@SequenceGenerator필요
  • TABLE : 키 생성용 테이블, 모든 DB에서 사용한다, @TableGenerator 필요
  • AUTO : DIALECT에 따라 자동 지정된다.(Default)

보통 기본키(PK)라고 하면 USER_IDPRODUCT_NUMBER등 객체와 관련된 컬럼을 생각합니다. 물론 저도 그렇고요..ㅎㅎ 그런데 JPA에서는 이러한 자동생성 전략을 지원해 줍니다. 그 이유는 무엇일까요?
바로 기본키는 바뀔 수 있기 때문입니다. 물론 사용자의 ID나 상품 번호등을 기본키로 기정하는 이유는 거의(대부분) 바뀔 일이 없기 때문입니다. 그러나 혹시라도 그럴 경우를 대비해서 Long을 이용한 숫자의 자동생성을 통해서 방지하는 것입니다.
또 자동생성전략에 int가 아닌 Long을 사용하는 이유는 자료형 크기 때문입니다. int보다는 Long이 크기때문에 보다 널널한? 데이터를 담을 수 있습니다.

권장하는 식별자 전략
기본키 제약조건 : null 아님, 유일, 변하면 안된다.
미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
예를 들어 주민등록번호도 기본키로 적절하지 않다.
권장 : Long + 대체키 + 키 생성전략사용

지금까지의 설정과 객체를 가지고 Transaction을 이용하여 객체를 다뤄보겠습니다.

전체 코드는 Github에서 확인해보실수 있습니다.

참고
  • HowtodoInJava (https://howtodoinjava.com/spring-boot2/h2-database-example/)
  • Baeldung (https://www.baeldung.com/spring-boot-h2-database)
  • SKplanet Academy (https://www.youtube.com/channel/UCtV98yyffjUORQRGTuLHomw)