관련된 글
- [JAVA] JPA(Java Persistence API)란?(1)
- [JAVA] JPA 기본설정 및 객체생성(2)
- [JAVA] JPA 어노테이션 및 트랜잭션(3)
- [JAVA] JPA 연관관계(4)
- [JAVA] JPA 영속성 컨텍스트(5)
1. 시작하기(환경설정)
이번 시간부터 실습을 통해서 JPA에 대해 알아보겠습니다.
실습환경은 다음과 같습니다.
- java 1.8
- Spring Boot 2.2.4.RELEASE
- H2 DataBase
H2 DataBase는 In-Memory형식으로 Test및 개발시 많이 사용하게 됩니다.(운영에서는 사용X)
- 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에서 web과 H2 데이터베이스와 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_ID나 PRODUCT_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)