인프런에서 우아한 형제들 김영한님의 JPA 강의를 학습하며 내용을 정리 해 보았습니다. 해당 강의를 들어보시길 추천합니다.
H2 데이터베이스는 자바기반의 오픈소스 RDBMS(관계형 데이터베이스 시스템)입니다. 인메모리 DB 기능을 지원하며 굉장히 용량도 작고 가볍게 동작하기 때문에 번거롭게 데이터베이스를 구축 할 필요 없이 손쉽게 실습을 할 수 있어 편리합니다.
H2 DATABASE 설치
아래의 공식 사이트에서 다운 받습니다. 저는 MacOS 를 사용중이기 때문에 All platforms 를 클릭 해 다운 받았습니다.
이후 적당한 폴더에 위치 시킵니다.
이제 h2/bin/h2.sh 를 실행 해줍니다.
bash h2.sh
Setting만 Server로 변경하고 아무 것도 바꾸지 않고 바로 Connect를 누르는데요, 보통 아래처럼 에러가 나옵니다.
그러면 데이터 베이스를 먼저 생성 해 주어야 합니다. 아래 처럼 JDBC에 아래 내용만 입력을 하고 한번 연결을 하면 데이터베이스 파일이 생성 됩니다.
jdbc:h2:~/test
이렇게 입력하고 Connect를 한번 눌러주면 접속이 됩니다.
생성 후에는 다시 아래 주소로 연결 하면 문제 없이 연결이 됩니다. 위에서처럼 파일에 직접 접근하는 방법은 lock 이 걸린다고 하네요.
jdbc:h2:tcp://localhost/~/test
이제 정상적으로 연결이 됩니다.
JAVA 프로젝트 생성
이제 프로젝트를 생성해봅니다 Maven으로 생성합니다.
Name이나 Location, GroupID, ArtifacdtId 등은 모두 편하신 대로 하면 됩니다.
프로젝트 생성이 완료되었습니다.
pom.xml에 dependency에 필요한 hibernate와 h2database를 넣어 줍니다.
h2 database는 아까 받았던 버전과 일치 시켜 줍니다.
<?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>com.tistory.shanepark</groupId>
<artifactId>ex1-hello-jpa</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.29.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
이번에는 Hibernate 설정파일을 만들어 줍니다. resources에 META-INF 디렉터리를 만든 후에 persistence.xml 파일을 생성 하면 됩니다.
<?xml version="1.0" encoding="utf-8" ?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
<persistence-unit name="hello">
<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"/>
</properties>
</persistence-unit>
</persistence>
이제는 EntityManagerFactory를 만들어 볼 건데요, 아까 위에서 만들었던 persistence.xml에 쓴 unit name을 적어 주면 됩니다.
package com.tistory.shanepark;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
}
}
이제 main 메서드를 실행 해보면 뭔가 문제 없이 커넥션이 진행 되는게 보입니다.
테이블 생성
다시 H2로 돌아와서 테스트를 위한 멤버 테이블을 생성합니다.
create table member(
id bigint not null,
name varchar(255),
primary key(id)
);
객체와 테이블 매핑
적당한 위치에 Member 클래스를 만들어 줍니다.
package com.tistory.shanepark;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Member {
@Id
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
이번에는 아까 작성했던 JpaMain 의 메인 메서드에 Member 를 insert 하는 내용을 작성 해 봅니다.
package com.tistory.shanepark;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
member.setId(1L);
member.setName("park");
em.persist(member);
tx.commit();
em.close();
emf.close();;
}
}
EntityManagerFactory 를 받아와서, EntityManager를 받아 온 뒤, 거기에서 Transaction을 받아 옵니다.
트랜잭션 안에서 Member를 생성 해서 em.persisst로 저장 해 주는 건데요. 이제 메인 메서드를 실행 해 보면
쿼리를 요청하는 것을 눈으로 확인 할 수 있습니다.
아까 persistence.xml에
옵션을 true로 했기 때문입니다.
정말 잘 들어갔는지 h2에 들어가서 확인 해 보면, 정말 park 이라는 멤버가 들어간게 확인 됩니다.
쿼리를 직접 짜지 않았지만, JPA가 알아서 Entity인 Member 클래스에서 관례에 따라 클래스명과 같은 Member 테이블을 찾아 insert 해 준 것 입니다.
클래스명이나 인스턴스 명이 테이블/컬럼명과 다를 경우에는 아래 처럼 수동으로 적어 줄 수도 있습니다.
package com.tistory.shanepark;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "MEMBER")
public class Member {
@Id
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
조회는 아래와 같이 할 수 있습니다.
package com.tistory.shanepark;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
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 findMember = em.find(Member.class, 1L);
System.out.println(findMember.getId());
System.out.println(findMember.getName());
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
emf.close();
}
}
}
select 쿼리를 날리고, 아이디인 1 과 , name인 park을 잘 받아 왔습니다.
수정의 경우는 findMember.persist(findMember)를 할 필요도 없이, 그냥 setter 만 호출 해 주면 알아서 저장이 됩니다.
Member findMember = em.find(Member.class, 1L);
findMember.setName("Shane Park");
tx.commit();
정말 기가 막힙니다!
편하게 자바 컬렉션을 다루는 것 처럼 사용 하면 되기 때문에 정말 편리합니다.
삭제도 어렵지 않습니다.
Member member = em.find(Member.class, 3L);
em.remove(member);
주의해 할 점
Entity Manager Factory 는 하나만 생성해서 어플리케이션 전체에서 공유
Entity Manager는 쓰레드간에 공유하면 절대 안됩니다. 사용하고 바로 버려야 합니다.
JPA의 모든 데이터 변경은 트랙잭션 안에서 실행되어야 합니다.
entityManager.createQuery를 이용하면 직접 쿼리를 작성 할 수도 있는데요
package com.tistory.shanepark;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
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 {
List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();
for (Member member : result) {
System.out.println("member.name = " + member.getName());
}
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
emf.close();
}
}
}
조금만 활용하면 페이지 네이션을 정말 쉽게 할 수 있습니다.
위와 같은 데이터가 있을 때
List<Member> result = em.createQuery("select m from Member as m", Member.class)
.setFirstResult(1).setMaxResults(2).getResultList();
setFirstResult로 1번째 결과부터 (0부터 세기때문에 jenny), setMaxResult로 최대2명까지 불러오게끔 할 수 있습니다.
쿼리에 limit 과 offset이 적용 되며 jenny 와 tommy가 조회 되는 것을 확인 하실 수 있습니다.
H2 데이터베이스를 설치해서 기본적인 CRUD를 해 보았는데요 JPA를 꼭 사용해야 하는 이유를 충분히 느끼셨을 거라고 생각합니다.
마지막으로 강의 링크 한번 더 남기며 글 마무리 짓겠습니다. 여유가 되시는 분은 꼭 강의를 들으시길 추천드려요.
'Programming > JPA ⁄ Spring' 카테고리의 다른 글
LDAP으로 스프링 시큐리티 인증하기 (0) | 2021.12.21 |
---|---|
JPA) 데이터베이스 스키마 자동 생성 (0) | 2021.09.22 |
Spring StopWatch.class 활용하기 (4) | 2021.08.31 |
IntelliJ IDEA) Devtools 사용해 HTML, CSS 등 정적자원 서버 재시작 없이 새로고침 (0) | 2021.08.25 |
SpringBoot ) Application.properties 혹은 .yml 프로필 별로 따로 사용하기 (Eclipse, IntelliJ IDEA) (0) | 2021.08.19 |