JPA
JPA (Java-Persistence-API)
JPA์ ํ์
JPA๋ ์๋ฐ์ RDBMS์ ํจ๋ฌ๋ค์์ ๋ถ์ผ์น๋ก ํ์ํ์์ผ๋ฉฐ ORM(Object-relational-mapping)์ด๋ค.
๊ฐ์ฒด vs ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค
- ์๋ฐ๋ ๊ฐ์ฒด ์งํฅ์ธ์ด๋ก ๊ฐ์ ์ค์ฌ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ํ
์ด๋ธ ์ค์ฌ์ด๋ค.
- ์ฐจ์ด์
- ์์
- ์ฐ๊ด๊ด๊ณ
- ๋ฐ์ดํฐ ํ์
- ๋ฐ์ดํฐ ์๋ณ ๋ฐฉ๋ฒ
์ด๋ฌํ ์ด์ ๋ฅผ ๊ฐ์ง๊ณ ๊ฐ์ฒด๋ต๊ฒ ๋ชจ๋ธ๋ง ํ ์๋ก ๋งตํ ์์ ๋ง ๋์ด๋๋ฉฐ, ๊ฐ๋ฐ์๋ JAVA์ฝ๋์ SQL ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๋ก ์์ฑํด์ผํ๋ ์๊ณ ๋ก์์ ๊ฐ์ง๊ณ ์์๋ค.
์ด๋ค ๊ฐ๋ฐ์๊ฐ โ๊ฐ์ฒด๋ฅผ ์๋ฐ ์ปฌ๋ ์ ์ ์ ์ฅ ํ๋ฏ์ด DB์ ์ ์ฅํ ์๋ ์์๊น?โ ์ ๊ทผํ ์ ์์ผ๋ฉด ์ด๋จ๊น ์๊ฐํ์ฌ ๋ง๋ค์ด์ง๊ฒ JPA์ด๋ค.
JPA ๋์ ์์น
java โ JPA โ JDBC โ SQL
ORM(Object-relational-mapping) ๊ฐ์ฒด
-
ORM์ ๊ฐ์ฒด์ RDB ๋ ๊ธฐ๋ฅ ์์ ์๋ ๊ธฐ์ ์ด๋ค
-
๊ด๊ณ ๋งคํ
- ๊ฐ์ฒด๋ ๊ฐ์ฒด๋๋ก ์ค๊ณ
- ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋๋ก ์ค๊ณ
- ORM ํ๋ ์์ํฌ๊ฐ ์ค๊ฐ์์ ๋งคํ
- ๋์ค์ ์ธ ์ธ์ด๋ ๋๋ถ๋ถ ORM ์ ์ฉ
JPA๋ฅผ ์ ์ฌ์ฉํด์ผ ํ๋๊ฐ
- SQL ์ค์ฌ์ ์ธ ๊ฐ๋ฐ์์ ๊ฐ์ฒด ์ค์ฌ์ผ๋ก ๊ฐ๋ฐ
- ์์ฐ์ฑ
- ์ ์ง๋ณด์
- JPA์ ํจ๋ฌ๋ค์์ ๋ถ์ผ์น ํด๊ฒฐ
- JPA์ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฅ
ํ๋ก์ ํธ ์์ฑ
Maven
dependency
์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋ค. JPA๋ ์ธํฐํ์ด์ค์ ๋ชจ์์ด๋ฉฐ 3๊ฐ์ง์ค ํ์ด๋ฒ๋ค์ดํธ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ค.
1. ํ์ด๋ฒ๋ค์ดํธ
2. EclipseLink
3. DataNucles
hibernate-entityManger๋ฅผ dependencyํ๋ฉด ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ค ๋ฐ์์ฌ ์ ์๋ค.
<!-- pom.xml -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.10.Final</version>
</dependency>
persistence.xml
JPA๋ pom.xml๋ง๊ณ ์ถ๊ฐ๋ก resource -> META-INF์ persistence.xml์ ์์ฑํด ์ฃผ์ด์ผ ํ๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<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"/> <!-- ์ฟผ๋ฆฌ ์คํ์ ๋ํ ์ ๋ณด ํ์ -->
<property name="hibernate.jdbc.batch_size" value="10"/> <!-- ํ์ด๋ฒ๋ค์ดํธ์์๋ value ์ฌ์ด์ฆ๋งํผ ๋ชจ์๋ค๊ฐ ํ๋ฒ์ ์ฟผ๋ฆฌ๋ฅผ ์คํ -->
<!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
JPA์ ๋์
JPA๋ Persistence๋ฅผ ์ฌ์ฉํ๋ฉฐ 3๊ฐ์ง์ ๊ฐ์ฒด๋ฅผ ํตํด ๋์ํ๊ฒ ๋๋ค.
1. EntitiyManagerFactory
2. EntityManager
3. EntityTransaction

EntitiyManagerFactory
EntitiyManagerFactory๋ JPA๋ฅผ ์ฌ์ฉ ํ ์ ์๋๋ก ํฉํ ๋ฆฌ ํด๋์ค๋ฅผ ๋ฑ๋กํด์ฃผ์ด์ผ ํ๋ค.
JPA ์คํ์ EntityManagerFactory๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ก๋ฉ์ ํ๋ฒ๋ง ์ ์ธํด์ค๋ค.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); // Persistence๋ฅผ ์ด์ฉํ์ฌ JPA ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ
EntityManager
EntityManager๋ ์์ฒญ์ด ์์๊ฒฝ์ฐ ์์ฑ๋๋ค.
EntityManager๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์ ์ ๊ฐ์ง๊ฒ ๋๋ฉฐ ๋์ ์๋ฃ ํ ๊ผญ close()๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.
ํธ๋ ์ ์ ๋จ์ DB์ปค๋ฅ์ => ์ฟผ๋ฆฌ์คํ => ์ข ๋ฃ (EntityManager ๋ฅผ ๋งค๋ฒ ์ ์ธ ํ์)
EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();
em.close();
EntityTransaction
EntityManager๋ฅผ ์ ์ธํ์ฌ persist([Entity.class]) ๋๋ [Entity.class].set~ , find() ํจ์๋ฅผ ํตํด ์ฟผ๋ฆฌ๋ฅผ ๋์ ํ ์ ์๋ค.
ํ์ง๋ง ์ด๋๋ก ์คํํ๋ค๋ฉด ์๋ฌด ์ฟผ๋ฆฌ๋ก ์คํ๋์ง ์์ ๊ฒ์ด๋ค.
์ด์ ๋ ํธ๋ ์ ์ ์ด ์ ์ธ๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
JPA๋ ํธ๋ ์ ์ ์์์๋ง ๋์ํ๋๋ก ๋์ด์์ผ๋ฉฐ ํธ๋ ์ ์ ๋จ์๊ฐ ๋งค์ฐ ์ค์ํ๋ค.
EntityTransaction ์ ์ ์ธํ์ฌ .begin() , .commit() ์ฌ์ด์ ์์ ์คํ์ด ๋๋ค.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
// JPA ์ฝ๋ ์์ฑ
tx.commit(); // ๋ก์ง ์ ์ ์ํ
} catch(Exception e) {
tx.rollback(); // ๋ก์ง ์ค๋ฅ ๋ฐ์์ ๋กค๋ฐฑ
} finally {
// close
em.close(); // EntityManager๋ ๋ฐ์ดํฐ์ปค๋ฅ์
์ ๋ฌผ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ผญ ๋ซ์์ค์ผํ๋ค.
}
emf.close();
JPA CRUD
MyBatis๋ฅผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์๋ค์ด ์ฒ์ JPA๋ฅผ ์ ํ๋ฉด ๋๋ ์ ๋ฐ์ ์๋ค.
JPA๋ ๊ฐ์ฒด์งํฅ๋งตํ์ผ๋ก @Entity ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฏ์ด CRUD๋ฅผ ํ ์ ์๋ค.
User Entity
@Entity
public class User {
@Id // PK๊ฐ ์ค์
private long id;
private String name;
public User() { // JPA๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฆฌํ๋์
์ ์ฌ์ฉํ๋ฉฐ ๋์ ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ์ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ๊ผญ ํ์ํ๋ค.
}
public Member(long id , String name) {
this.id = id;
this.name = 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;
}
}
INSERT
Mybatis์์ ํ๋ INSERT๋
INSERT INTO user(id , name)VALUES(1L , 'HelloB')
์ ๊ฐ์ด mapper.xml์ ์์ฑํ์ฌ ๋งตํ์ ์์บฌ์ค์ผํ๋ค. ํ์ง๋ง JPA๋ ๋งค์ฐ ๊ฐ๋จํ๊ฒ Insert๋ฅผ ํ ์ ์๋ค.
User user = new User();
user.setId(1L);
user.setName("HelloB");
em.persist(user);
SELECT
์กฐํ๋ .find(Entity , pk)๋ฅผ ํตํด ๊ฐ๋จํ๊ฒ ์กฐํ ํ ์ ์๋ค.
SELECT * FROM user WHERE id = 1L
User findUser = em.find(User.class, 1L);
UPDATE
์์ ์ ๋งค์ฐ ๊ฐ๋จํ๋ค. ์๋ฐ์์ ์ปฌ๋ ์
์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ ๋ฐ๋ก ์
๋ฐ์ดํธ๋ฅผ ํด์ฃผ์ง ์๋๋ค.
JPA๋ ๋๊ฐ์ ๊ฐ๋
์ ์ ์ฉํ๋ฉฐ findํ ๋ฐ์ดํฐ๋ฅผ set ๋ฉ์๋๋ฅผ ํตํด ๊ฐ๋ง ๋ณ๊ฒฝํ๋ฉด ์
๋ฐ์ดํธ ์ฟผ๋ฆฌ๋ฅผ ์๋์ผ๋ก ๋ ๋ ค์ค๋ค.
UPDATE user SET name = 'HelloJPA' WHERE id = 1L
User findUser = em.find(User.class, 1L);
findUser.setName("HelloJPA");
DELETE
User findUser = em.find(User.class, 1L);
findUser.remove();
CRUD๊ฐ ๋งค์ฐ ํธ๋ฆฌํด์ง๊ณ ๊ฐํธํด์ก๋ค. ์ด๋ฌํ ๋์์๋ฆฌ๋ ์์์ฑ ์ปจํ ์คํธ๋ผ๋ ๋ ผ๋ฆฌ์ ๊ฐ๋ ์ด ์ ์ฉ๋์ด ์์ด ์ด๋ ๊ฒ ๋์ ํ ์ ์๋ค.
JPA ํน์ฑ
๊ฐ๊ฐ ๋ฐ์ดํฐ ๋ฒ ์ด์ค๋ ๋น์ทํ์ง๋ง ๊ฐ์ ๋ค๋ฅธ ํจ์์ ๋ฌธ๋ฒ์ ๊ฐ์ง๊ณ ์๋ค. ๊ฐ๋ฐ์๋ ํญ์ DB๊ฐ ๋ฐ๋๋ฉด ๋ง๋ ๋ฌธ๋ฒ์ผ๋ก ๋ณ๊ฒฝํด์ค์ผํ๋ฉฐ DB์ ์์กด์ฑ์ ๊ฐ์ง๊ฒ ๋๋ค.
JPA์์๋ ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฌธ๋ฒ์ด๋ ํจ์๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐฉ์ธ์ด๋ผ ์นญํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐฉ์ธ
- JPA๋ ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ข ์ X
- ๊ฐ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ ๊ณตํ๋ SQL ๋ฌธ๋ฒ๊ณผ ํจ์๋ ์กฐ๊ธ์ฉ ๋ค๋ฆ
- ๊ฐ๋ณ ๋ฌธ์ : MySQL์ VARCHAR , Oracle ์ VARCHAR2
- ๋ฌธ์์ด์ ์๋ฅด๋ ํจ์ : SQL ํ์ค์ SUBSTRING(), Oracle์ SUBSTR()
- ํ์ด์ง MySQL์ LIMIT , Oracle์ ROWNUM
- ๋ฐฉ์ธ : SQL ํ์ค์ ์งํค์ง ์๋ ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง์ ๊ณ ์ ํ ๊ธฐ๋ฅ
JPA์์๋ ์ด์ ๊ฐ์ด ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ฐฉ์ธ์ ๊ฐ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ง๊ฒ ๋์ ์ผ๋ก ๋ณํํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค์ค๋ค.
(hibernate.dialect ์ค์)
JPQL
JPA๋ ํ ์ด๋ธ์ ๋์์ผ๋ก ์ฝ๋๋ฅผ ์ง์ง ์์ผ๋ฉฐ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์ค์ฌ์ผ๋ก ๊ฐ๋ฐ (๊ฐ์ฒด๋ฅผ ๋์์ผ๋กํ๋ ๊ฐ์ฒด์งํฅ ์ฟผ๋ฆฌ).
ํ์ง๋ง ์ฌ์ฉํ๋ฉด ๋ฌธ์ ์ ์ด ์๋ค. ์ฐ๋ฆฌ๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์กฐ์ธ๊ณผ ๊ฒ์ ์ฟผ๋ฆฌ๋ฅผ ๋ง์ด ์์ฑํ๊ฒ๋๋ค.
๊ฒ์ ์ฟผ๋ฆฌ๋ฅผ JPA๋ก๋ง ์์ฑํ๊ธฐ์๋ ๋ง์ ๋ฌธ์ ๊ฐ ์๋ค.
1. ๊ฒ์ ์ฟผ๋ฆฌ
2. ๊ฒ์์ ํ ๋๋ ํ
์ด๋ธ์ด ์๋ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ๊ฒ์
3. ๋ชจ๋ DB ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํด์ ๊ฒ์ํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅ
4. ์ ํ๋ฆฌ์ผ์ด์
์ด ํ์ํ ๋ฐ์ดํฐ๋ง DB์์ ๋ถ๋ฌ์ค๋ ค๋ฉด ๊ฒฐ๊ตญ ๊ฒ์ ์กฐ๊ฑด์ด ํฌํจ๋ SQL์ด ํ์
์ด๋ฌํ ๋ฌธ์ ๋ฅผ JPQL์ ์ฌ์ฉํ๋ฉด ์ด๋์ ๋ ํด๊ฒฐ ํ ์ ์๋ค.
ex) JPQL์ฌ์ฉ
-
em.createQuery(โselect m from Member as mโ , [Entity.class])
. setFirstResult(1) // MySQL : LIMIT , ORACLE : ROWNUM (์์ ๋ฒํธ) . setMaxResult(5) // (๊ฐ์ ธ์ค๋ ๊ฐฏ์) . getResultList(); -
์์ ๊ฐ์ด ๋ฐ์ดํฐ ๋ฒ ์ด์ค์ ๋ง๋ ๋ฌธ๋ฒ์ผ๋ก ๋ณํํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ์คํํด์ค๋ค.
์ค๋ฌด์์ JPQL ์์ด๋ ์์ ์ด ๊ฑฐ์ ๋ถ๊ฐ๋ฅํ๋ค. (์์ธ์กฐํ ๋ฐ ์กฐ์ธ ์ฟผ๋ฆฌ ์์ฑ)
Leave a comment