카카오 클라우드 교육과정 중 데이터베이스에 대해서 공부하면서 조인 기능과 서브쿼리를 이용해서 내가 원하는 데이터를 조회하는데 있어서 상황에 따라 성능을 최적화할 수 있다는 것을 알게 되었다.
그리고 조인을 사용했을 때와 서브쿼리를 사용했을 때 시간을 비교해보면서 어떻게 SQL문을 작성해야하는지 알게 되었고, ERD 설계의 중요성도 알게 되었다.
이처럼 나는 현재 Java를 공부하고 있고 관계형 데이터베이스를 사용하여 프로젝트를 진행할 계획에 있다. 하지만 Java는 객체 중심의 구조를 가지고 있고, 데이터 베이스는 데이터 중심의 구조를 가지고 있어서 다양한 패러다임의 불일치로 인한 문제가 발생한다. (어떠한 패러다임의 불일치가 발생하는지에 대한 설명은 생략하려고한다.)
따라서 서로 다른 관점을 가지고 있어 발생한 패러다임의 불일치를 해결해줄 수 있는 Java 진영의 ORM 표준 프레임워크인 JPA에 대해서 학습해보려고한다.
JPA에 대해서 학습하는 것은 자바 ORM 표준 JPA 프로그래밍 책을 읽고 실습해보면서 글을 작성해보려고한다.
CREATE TABLE MEMBER (
ID VARCHAR(255) NOT NULL,
NAME VARCHAR(255),
AGE INTEGER,
PRIMARY KEY (ID)
)
아이디 (기본 키)
, 이름
, 나이
를 필드를 가지고 있는 회원 테이블을 이용하려고 한다.
public class Member {
private String id;
private String username;
private Integer age;
public String getId() { return id; }
public void setId(String 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; }
}
그리고 위에서 정의한 MEMBER 테이블을 자바에서 객체로 나타내면 위와 같이 각 테이블의 속성을 필드로 선언하고 Getter, Setter 메소드를 만들어 관리해야한다.
그렇다면 이번에는 JPA에서 제공하는 매핑 어노테이션을 이용하여 사진과 같이 매핑을 해보자.
@Entity
@Table(name="MEMBER")
public class Member {
@Id
@Column(name = "ID")
private String id;
@Column(name = "NAME")
private String username;
private Integer age;
public String getId() {
return id;
}
public void setId(String 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;
}
}
코드를 살펴보면 @Entity
, @Table
, @Id
, @Column
을 통해 JPA가 어떠한 객체를 이용하여 DB 내 테이블에 저장해야하는지 알 수 있도록 매핑을 한 것이다.
따라서 간단하게 각 어노테이션에 대해 알아보자.
@Entity는 해당 클래스를 매핑하기 위한 객체라는 것을 JPA에게 알려주는 역할을 한다.
@Table은 @Entity가 붙은 클래스가 어떤 테이블과 매핑해야하는지 알려주는 역할을 한다.
코드를 살펴보면 name속성에 MEMBER값이 작성되어있다. 즉, name 속성에 어떠한 테이블과 매핑해야하는지 JPA에게 알려준다.
그리고 @Table 어노테이션을 작성하지 않으면 클래스 이름을 테이블 이름으로 자동으로 매핑한다.
@Id는 @Entity가 붙은 클래스의 기본키(필드 식별자)를 알려주는 역할을 한다. 작성한 코드에서는 id 변수가 기본키라는 것을 알려준다.
@Column은 필드를 속성(컬럼)과 매핑하는 역할을 한다. name 속성을 이용할 수 있는데 작성한 코드를 살펴보면 username 필드를 MEMBER테이블의 NAME 컬럼과 매핑한 것이다.
작성 코드를 살펴보면 @Column이 붙어있지 않는 필드도 볼 수 있다. @Column어노테이션을 사용하는 것이 필수는 아니며 사용하지 않으면 필드명을 테이블의 속성으로 자동으로 매핑해준다. 즉, age변수는 자동적으로 AGE속성으로 매핑된다는 것이다.
JPA는 persistence.xml파일을 이용하여 설정 정보를 관리한다.
persistence.xml은 META-INF/persistence.xml 경로에 있으면 추가 설정 없이 JPA가 자동으로 인식할 수 있다.
<?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>
해당 파일은 <persistence>
로 시작한다. 그리고 persistence태그에는 XML 네임스페이스와 사용 버전을 명시한다.
🤔 namespace란 ?
요소와 속성의 이름을 유일하게 식별할 수 있도록 하기 위해 사용한다.
즉, Java에서 정의된 퍼시스턴스 관련 API의 네임스페이스를 해당 XML파일에서 사용하겠다는 의미 인것이다.
그리고 <persistence-unit
>태그를 이용한다.
해당 태그는 연결할 데이터베이스 당 하나의 영속성 유닛을 작성한다.
<persistence-unit name="jpabook">
코드를 살펴보면, 영속성 유닛으로 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" /> <!-- 실행 SQL 출력 옵션 -->
<property name="hibernate.format_sql" value="true" /> <!-- 실행 SQL 출력 정렬 옵션 -->
<property name="hibernate.use_sql_comments" value="true" /> <!-- 쿼리 출력시 주석 동시 출력 옵션 -->
<property name="hibernate.id.new_generator_mappings" value="true" /> <!-- JPA 표준에 맞춘 새로운 키 생성 전략 사용 -->
<!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
</properties>
속성은 여러가지를 등록할 수 있으며, <properties>
태그 내부에 여러개의 <property>
태그를 작성하여 속성을 등록한다.
속성에 대해서는 간단하게 알아보자