본문 바로가기
Study/spring

자바 ORM 표준 JPA 프로그래밍(2) - JPA 시작

by 유경호 2020. 12. 4.
반응형

메이븐과 사용 라이브러리 관리

메이븐 설정 파일 pom.xml

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>jpabook</groupId>
    <artifactId>ch02-jpa-start1</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <properties>
 
        <!-- 기본 설정 -->
        <java.version>1.6</java.version>
        <!-- 프로젝트 코드 인코딩 설정 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
        <!-- JPA, 하이버네이트 버전 -->
        <hibernate.version>4.3.10.Final</hibernate.version>
        <!-- 데이터베이스 버전 -->
        <h2db.version>1.4.187</h2db.version>
 
    </properties>
 
    <dependencies>
        <!-- JPA, 하이버네이트 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <!-- H2 데이터베이스 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2db.version}</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
</project>
cs

 

<dependencies>에 사용할 라이브러리를 지정한다. groupId + artifactId + version만 적어주면 라이브러리(jar 파일)를 메이븐 공식 저장소에서 내려받아 라이브러리에 추가해준다.

  • JPA, 하이버네이트(hibernate-entitymanager): JPA 표준과 하이버네이트를 포함하는 라이브러리, hibernate-entitymanager를 라이브러리로 지정하면 다음 중 두 라이브러리도 함께 내려받는다.
     - hibernate-core.jar
     - hibernate-jpa-2.1-api.jar

객체 매핑 시작

회원 테이블

1
2
3
4
5
6
7
SELECT * FROM `spring-boot-jpa-test`.member;CREATE TABLE `member` (
  `MEMBER_NO` int NOT NULL AUTO_INCREMENT,
  `ID` varchar(200COLLATE utf8_bin DEFAULT NULL,
  `NAME` varchar(200COLLATE utf8_bin DEFAULT NULL,
  `AGE` int DEFAULT NULL,
  PRIMARY KEY (`MEMBER_NO`)
)
cs

 

회원 클래스

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
import lombok.*;
import javax.persistence.*;
 
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity(name = "member"// @Entity가 붙은 클래스는 JPA가 관리하는 클래스, 테이블과 매핑할 VO 클래스에 해당 어노테이션을 붙인다.
public class MemberVO {
    @Id // @Id를 사용하여 기본키(PK)로 지정한다.
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 기본 키 생성 Strategy를 데이터 베이스에 위임하는 방식(그 외 (IDENTITY, SEQUENCE, TABLE, AUTO 등이 있다.)을 체택
    @Column(name = "MEMBER_NO")
    private Long memberNo;
    @Column(name = "ID")
    private String id;
    @Column(name = "NAME")
    private String userName;
    // 매핑 정보가 없는 필드
    private Integer age;
 
    @Builder
    public MemberVO(String id, String userName, Integer age) {
        super();
        this.id = id;
        this.userName = userName;
        this.age = age;
    }
}
cs

 

어노테이션 설명

@Entity

이 클래스를 테이블과 매핑한다고 JPA에게 알려준다. 이렇게 @Entity가 사용된 클래스를 엔티티 클래스라 한다.

@Table

엔티티 클래스에 매핑할 테이블 정보를 알려준다. 여기서는 name 속성을 사용해서 Member 엔티티를 MEMBER 테이블에 매핑했다. 이 어노테이션을 생략하면 클래스 이름을 테이블 이름으로 매핑한다. (정확히는 엔티티 이름을 사용한다.)

@Id

엔티티 클래스의 필드를 테이블의 기본 키(Primary key)에 매핑한다. 여기서는 엔티티의 id 필드를 테이블의 ID 기본 키 칼럼에 매핑했다. 이렇게 @Id가 사용된 필드를 식별자 필드라 한다.

@Column

필드를 칼럼에 매핑한다. 여기서는 name 속성을 사용해서 Member 엔티티의 userName 필드를 MEMBER 테이블의 NAME 컬럼에 매핑했다.

매핑 정보가 없는 필드

age 필드에는 매핑 어노테이션이 없다. 이렇게 매핑 어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 매핑한다. 여기서는 필드명이 age이므로 age 컬럼으로 매핑했다. 참고로 이 책에서는 데이터베이스가 대소문자를 구분하지 않는다고 가정한다. 만약 대소문자를 구분하는 데이터베이스를 사용하면 @Cloumn(name = "AGE") 처럼 명시적으로 매핑해야 한다.

매핑 정보 덕분에 JPA는 어떤 엔티티를 어떤 테이블에 저장해야 하는지 알 수 있다.

persistence.xml 설정

JPA는 persistence.xml을 사용해서 필요한 설정 정보를 관리한다. 이 설정 파일이 META-INF/persisntence.xml 클래스 패스 경로에 있으면 별도의 설정 없이 JPA가 인식할 수 있다.

persistence.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
 
    <persistence-unit name="jpabook">
 
        <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: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.id.new_generator_mappings" value="true" />
 
            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>
 
</persistence>
cs

 

  • JPA 표준 속성
    • javax.persistence.jdbc.driver: JDBC 드라이버
    • javax.persistence.jdbc.user: 데이터베이스 접속 아이디
    • javax.persistence.jdbc.password: 데이터베이스 접속 패스워드
    • javax.persistence.jdbc.url: 데이터베이스 접속 URL
  • 하이버네이트 속성
    • hibernate.dialect: 데이터베이스 방언(Dialect) 설정
    • hibernate.show_sql: 하이버네이트가 실행한 SQL을 출력한다.
    • hibernate.format_sql: 하이버네이트가 실행한 SQL을 출력할 때 보기 쉽게 정렬한다.
    • hibernate.use_sql_comments: 쿼리를 출력할 때 주석도 함께 출력한다.
    • hibernate.id.new_generator_mappings: JPA 표준에 맞춘 새로운 키 생성 전략을 사용한다.

이름이 javax.persistence로 시작하는 속성은 JPA 표준 속성으로 특정 구현체에 종속되지 않는다. 반면에 hibernate로 시작하는 속성은 하이버네이트 전용 속성이므로 하이버네이트에서만 사용할 수 있다.

참고로 스프링 부트로 Spring Data JPA를 사용할 경우에는 아래와 같이 properties를 작성해주면 된다. 요소들의 맥락은 위 내용과 일치한다.

 

application.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#JPA 설정
#Dialect 설정
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
#하이버네이트가 실행하는 모든 SQL문을 콘솔로 출력해 준다.
spring.jpa.properties.hibernate.show_sql=true
#콘솔에 출력되는 JPA 실행 쿼리를 가독성있게 표현한다.
spring.jpa.properties.hibernate.format_sql=true
#디버깅이 용이하도록 SQL문 이외에 추가적인 정보를 출력해 준다.
spring.jpa.properties.hibernate.use_sql_comments=true
 
#Datasource 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring-boot-jpa-test?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=
cs

 

데이터베이스 방언(Dialect)

JPA는 특정 데이터베이스에 종속적이지 않은 기술이다. 하지만 각 데이터베이스가 제공하는 SQL 문법과 함수들에 차이가 있다는 문제가 발생한다. 예를 들면 데이터베이스간에 아래와 같은 차이점이 있다.

  • 데이터 타입: 가변 문자 타입으로 MySQL은 VARCHAR, 오라클은 VARCHAR2를 사용한다.
  • 다른 함수명: 문자열을 자르는 함수로 SQL 표준은 SUBSTRING()을 사용하지만 오라클은 SUBSTR()을 사용한다.
  • 페이징 처리: MySQL은 LIMIT을 사용하지만 오라클은 ROWNUM을 사용한다.
반응형