ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๐Ÿ’กJPA ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ

๐Ÿ’ป JPA ๊ตฌ๋™ ๋ฐฉ์‹

package hellojpa;

import jakarta.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{
        	//๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
            Member member = new Member();
            member.setId(2L);
            member.setName("HelloB");
            
            em.persist(member);
			
            //ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹
            tx.commit();
        } catch (Exception e) {
        	//ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ
            tx.rollback();
        } finally {
        	//์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ์ข…๋ฃŒ
            em.close();
        }
        //์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ ์ข…๋ฃŒ
        emf.close();
    }
}

 

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด EntityManagerFactory(์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ), EntityManager(์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €), Transaction(ํŠธ๋žœ์žญ์…˜)์ด ๋ณด์ผ ๊ฒƒ์ด๋‹ค.  ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž.

 

๋จผ์ € JPA์˜ ๊ตฌ๋™๋ฐฉ์‹์€ ์œ„์™€ ๊ฐ™๋‹ค.

 

  1. ์„ค์ • ์ •๋ณด ์กฐํšŒ (Configuration Load):
    • JPA๋Š” ์‹œ์ž‘๋  ๋•Œ persistence.xml์ด๋ผ๋Š” XML ํŒŒ์ผ์„ ์ฐธ์กฐํ•œ๋‹ค. ์ด ํŒŒ์ผ์€ META-INF ๋””๋ ‰ํ† ๋ฆฌ์— ์œ„์น˜ํ•˜๋ฉฐ, JPA๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์—ฌ๋Ÿฌ ์„ค์ •์„ ํฌํ•จํ•œ๋‹ค. ์ด ์„ค์ •์—๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ •๋ณด, ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ์„ค์ •, ํŠธ๋žœ์žญ์…˜ ํƒ€์ž… ๋“ฑ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค. 
<?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="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="sa"/>
            <property name="jakarta.persistence.jdbc.password" value=""/>
            <property name="jakarta.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.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>

</persistence>

 

 

    2. EntityManagerFactory ์ƒ์„ฑ (Bootstrap):

  • ์„ค์ • ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ JPA๋Š” EntityManagerFactory๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. Persistence ํด๋ž˜์Šค๋Š” ์ด ๊ณผ์ •์—์„œ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๋‹จ ํ•˜๋‚˜์˜ EntityManagerFactory ์ธ์Šคํ„ด์Šค๋งŒ ์กด์žฌํ•˜๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค. EntityManagerFactory๋Š” ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๊ฐ์ฒด์ด๋ฏ€๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์—์„œ ์žฌ์‚ฌ์šฉ๋œ๋‹ค.

   3. EntityManager ์ƒ์„ฑ (Run-time):

  • EntityManagerFactory๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค EntityManager ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. EntityManager๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , CRUD ์ž‘์—…์„ ์œ„ํ•œ API๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ๊ฐ EntityManager ์ธ์Šคํ„ด์Šค๋Š” ํ•˜๋‚˜์˜ ์ž‘์—… ๋‹จ์œ„(๋ณดํ†ต ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜)์— ๋Œ€ํ•ด ์ƒ์„ฑ๋˜๋ฉฐ, ์ž‘์—…์ด ๋๋‚œ ํ›„์—๋Š” ์ข…๋ฃŒ๋œ๋‹ค. ๊ฐ๊ฐ์˜ EntityManager๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ๊ณผ ์บ์‹œ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ํŠธ๋žœ์žญ์…˜ ๋‹น ํ•˜๋‚˜์”ฉ ์‚ฌ์šฉ๋˜๊ณ  ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚œ ํ›„์—๋Š” ํ๊ธฐ๋œ๋‹ค.

์ฃผ์˜

  • EntityManagerFactory(์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ํŒฉํ† ๋ฆฌ)๋Š” ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•ด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๊ณต์œ ํ•œ๋‹ค.
  • EntityManager(์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €)๋Š” ์“ฐ๋ ˆ๋“œ ๊ฐ„์— ๊ณต์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค. (์‚ฌ์šฉํ•˜๊ณ  ๋ฒ„๋ ค์•ผ ํ•œ๋‹ค.)
  • JPA์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์€ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.
EntityTransaction tx = em.getTransaction();
        tx.begin(); //ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘

        try{
        	//๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
            Member member = new Member();
            member.setId(2L);
            member.setName("HelloB");
            
            em.persist(member);
			
            //ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹
            tx.commit();
        } catch (Exception e) {
        	//ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ
            tx.rollback();
        } finally {
        	//์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ € ์ข…๋ฃŒ
            em.close();
        }

 

๋ณดํ†ต ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•˜๊ณ (tx.commit()), ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑ(tx.rollback())ํ•œ๋‹ค.

 

๐Ÿ’ป  ์‹ค์Šต - ํšŒ์› ์ €์žฅ

JPA๋ฅผ ํ™œ์šฉํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ์ถ”์ƒํ™”ํ•˜์—ฌ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘์ ์ธ SQL ํ•ธ๋“ค๋ง ์—†์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. 

 

์—”ํ‹ฐํ‹ฐ ๋“ฑ๋ก

Member member = new Member();
member.setId(2L);
member.setName("helloB");

em.persist(member);
  • 'persist()' ๋ฉ”์„œ๋“œ๋Š” ์ƒˆ๋กœ์šด ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด ๋•Œ ๋ฐœ์ƒํ•˜๋Š” SQL์€ ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋  ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜๋œ๋‹ค.

๋‹จ์ผ ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ

Member member = em.find(Member.class, id);
  • 'find()' ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž…๊ณผ ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•ด ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐพ๋Š”๋‹ค.
  • ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ด๋ฏธ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด์— ์žˆ์œผ๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐํšŒํ•˜์ง€ ์•Š๊ณ  ์บ์‹œ๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 
  • ์—†์œผ๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ๋“ฑ๋กํ•œ๋‹ค.

์—”ํ‹ฐํ‹ฐ ์‚ญ์ œ

em.remove(member);
  • 'remove()' ๋ฉ”์„œ๋“œ๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ์ œ๊ฑฐํ•˜๋ฉฐ, ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์‚ญ์ œํ•œ๋‹ค.

์—”ํ‹ฐํ‹ฐ ์ˆ˜์ •

Member member = em.find(Member.class, id);
member.setName("member01");
  • ์—”ํ‹ฐํ‹ฐ์˜ ์ˆ˜์ •์€ 'em.update()'๋‚˜ 'em.persist()'๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ ๋„ ํ•„๋“œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ๋ฐ˜์˜๋œ๋‹ค.
  • JPA๋Š” ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ์‹œ์ ์— ์—”ํ‹ฐํ‹ฐ์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ('Dirty Checking'), ๋ณ€๊ฒฝ๋œ ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•œ 'UPDATE' SQL์„ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•œ๋‹ค.

๐Ÿ’ป  ์‹ค์Šต - JPQL(Java Persistence Query Language) ์†Œ๊ฐœ 

  • JPA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์—์„œ๋Š” ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋ถ€๋ถ„์ด ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์ด๋‹ค. 
  • ํ…Œ์ด๋ธ”์ด ์•„๋‹Œ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ์ „ํ™˜ํ•˜์—ฌ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. 
  • ๊ทธ ๊ฒฐ๊ณผ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•„์š”๋กœ ํ•˜๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๋งŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํšจ์œจ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๊ฒ€์ƒ‰ ์กฐ๊ฑด์„ ํฌํ•จํ•˜๋Š” SQL ์ž‘์„ฑ์ด ํ•„์ˆ˜์ ์ด๋‹ค.
  • ๋”ฐ๋ผ์„œ JPA๋Š” SQL์„ ์ถ”์ƒํ™”ํ•œ JPQL์ด๋ผ๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

JPQL์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด๋กœ, ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•œ๋‹ค. ์ด๋Š” SQL์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋Œ€์กฐ๋œ๋‹ค.

 

JPQL์€ 'SELECT', 'FROM', 'WHERE', 'GROUP BY', 'HAVING', 'JOIN' ๋“ฑ์˜ SQL๊ณผ ์œ ์‚ฌํ•œ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ์ฒ˜๋ฆฌ์˜ ๋Œ€์ƒ์ด ๊ฐ์ฒด์˜ ์ƒํƒœ์™€ ๊ด€๊ณ„๋ฅผ ๋ฐ˜์˜ํ•˜๋Š” ํด๋ž˜์Šค์™€ ํ•„๋“œ์ด๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด,

List<Member> result = em.createQuery("SELECT m FROM Member m", Member.class)
		.setFirstResult(5)
        	.setMaxResults(8) //ํŽ˜์ด์ง• (5๋ฒˆ๋ถ€ํ„ฐ 8๊ฐœ ๊ฐ€์ ธ์™€)
        	.getResultList();
        
for (Member member : result) {
    System.out.println("member.name = " + member.getName());
}
  • createQuery() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ JPQL ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋กœ TypedQuery ๊ฐ์ฒด๋ฅผ ์–ป๋Š”๋‹ค.
  • ์ด ์ฟผ๋ฆฌ ๊ฐ์ฒด์˜ getResultList() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, JPA๋Š” JPQL์„ ๋ถ„์„ํ•˜๊ณ  ํ•ด๋‹นํ•˜๋Š” SQL์„ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•œ๋‹ค. ์กฐํšŒ๋œ ๋ฐ์ดํ„ฐ๋Š” ์ง€์ •๋œ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž…์˜ ๊ฐ์ฒด ๋ชฉ๋ก์œผ๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.

 

๐Ÿ’ก๊ฒฐ๋ก 

JPA์˜ ์ด๋Ÿฌํ•œ ์ž‘์—…๋“ค์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ๊ฐœ๋ฐœ์ž๋กœ๋ถ€ํ„ฐ ์ถ”์ƒํ™”ํ•˜๊ณ , ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค๋ฅผ ํ†ต์ผ๋œ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

์ด๊ฒƒ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒ์‚ฐ์„ฑ๊ณผ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์ด์ ์„ ์ œ๊ณตํ•œ๋‹ค.