JPA
λ°μ΄ν°λ² μ΄μ€μ κ°μ²΄(Entity) κ° μλ λ§€νμ ν΅ν΄ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλ μλ° ORM νλ μμν¬
β’
JPA
β’
JPA μ£Όμ κ΅¬μ± μμ
β’
JPA μ₯μ
β’
JPA vs MyBatis
β’
JPA μ£Όμ κΈ°λ₯
JPAλ?
JPA(Java Persistence API)λ μλ° μ§μμ ORM κΈ°μ νμ€μ
λλ€. JPAλ₯Ό μ¬μ©νλ©΄ κ°λ°μκ° μ§μ SQLμ μμ±νμ§ μκ³ λ λ°μ΄ν°λ² μ΄μ€λ₯Ό κ°μ²΄μ§ν₯μ μΌλ‘ κ΄λ¦¬ν μ μμ΅λλ€.
JPA μ£Όμ κ΅¬μ± μμ
κ΅¬μ± μμ | μν λ° μ€λͺ
|
Persistence Unit | JPA μ€μ μ 보λ₯Ό μ μνλ λ
Όλ¦¬μ λ¨μ. DB μ°κ²° μ 보 λ° μν°ν° λͺ©λ‘μ ν¬ν¨. (persistence.xml λλ application.ymlμμ μ€μ ) |
Entities (μν°ν°) | λ°μ΄ν°λ² μ΄μ€ ν
μ΄λΈκ³Ό 1:1 λ§€νλλ κ°μ²΄.
@Entity μ΄λ
Έν
μ΄μ
μΌλ‘ μ μνλ©°, @Idλ‘ κΈ°λ³Έ ν€ μ§μ . |
EntityManagerFactory | EntityManagerλ₯Ό μμ±νλ ν©ν 리 κ°μ²΄. μ ν리μΌμ΄μ
μμ νλλ§ μμ±νλ©°
μ¬λ¬ EntityManager μ 곡. |
EntityManager | μν°ν°μ μ μ₯, μ‘°ν, μμ , μμ λ₯Ό λ΄λΉνλ ν΅μ¬ κ°μ²΄.
persist(), find(), remove() λ±μ λ©μλλ₯Ό μ 곡. |
PersistenceContext | μν°ν°μ μνλ₯Ό μΆμ νλ JPAμ 1μ°¨ μΊμ μν .
λ³κ²½ κ°μ§(Dirty Checking)λ₯Ό ν΅ν΄ μλμΌλ‘ λ³κ²½ μ¬ν λ°μ. |
TransactionManager | λ°μ΄ν° λ³κ²½ μ νΈλμμ
μ κ΄λ¦¬νμ¬ μ ν©μ±μ 보μ₯.
Spring Bootμμλ @Transactionalλ‘ νΈλμμ
μ μ© κ°λ₯. |
DB (Database) | JPAκ° μ°λνλ μ΅μ’
μ μ₯μ.
Hibernate λ± κ΅¬ν체λ₯Ό μ¬μ©νμ¬ SQLμ μλ μμ±νκ³ λ°μ΄ν° κ΄λ¦¬ μν. |
JPA ꡬ쑰 λ° κ° μμμ μν
JPA(Java Persistence API)λ κ°μ²΄μ λ°μ΄ν°λ² μ΄μ€ κ°μ λ§€νμ μλννλ ORM(Object-Relational Mapping) κΈ°μ μ
λλ€.
Persistence Unit (νΌμμ€ν΄μ€ μ λ)
JPA μ€μ μ 보λ₯Ό μ μνλ λ
Όλ¦¬μ λ¨μμ
λλ€.
β’
JPAκ° μ΄λ€ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©ν μ§, μ΄λ€ μν°ν°λ₯Ό κ΄λ¦¬ν μ§ λ±μ μ€μ μ ν¬ν¨ν©λλ€.
β’
Java SE νκ²½μμλ persistence.xml νμΌμμ μ€μ νμ§λ§, Spring Bootμμλ application.properties λλ application.ymlμμ μ€μ ν©λλ€.
β’
Persistence Unitμ΄ μ μλλ©΄, JPAκ° μ΄λ₯Ό κΈ°λ°μΌλ‘ λμνλ©° λ°μ΄ν°λ² μ΄μ€ μ°κ²°μ κ΄λ¦¬ν©λλ€.
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=1234
spring.jpa.hibernate.ddl-auto=update
Plain Text
볡μ¬
Entities (μν°ν°)
λ°μ΄ν°λ² μ΄μ€ ν
μ΄λΈκ³Ό 1:1 λ§€νλλ κ°μ²΄μ
λλ€.
β’
@Entity μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ¬ JPAκ° ν΄λΉ ν΄λμ€λ₯Ό μν°ν°λ‘ μΈμνλλ‘ ν©λλ€.
β’
κ° νλλ λ°μ΄ν°λ² μ΄μ€μ 컬λΌκ³Ό λ§€νλλ©°, @Idλ κΈ°λ³Έ ν€λ₯Ό μλ―Έν©λλ€.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
Java
볡μ¬
EntityManagerFactory (μν°ν° λ§€λμ ν©ν 리)
EntityManagerλ₯Ό μμ±νλ ν©ν 리(Factory) κ°μ²΄μ
λλ€.
β’
JPAμμλ EntityManagerκ° λ°μ΄ν°λ² μ΄μ€μμ μ°κ²°μ κ΄λ¦¬νμ§λ§, EntityManagerFactoryλ EntityManagerμ μμ±μ λ΄λΉν©λλ€.
β’
μΌλ°μ μΌλ‘ μ ν리μΌμ΄μ
μμ νλλ§ μμ±νλ©°, μ¬λ¬ κ°μ EntityManagerλ₯Ό μ 곡ν μ μμ΅λλ€.
@Autowired
private EntityManagerFactory entityManagerFactory;
Java
볡μ¬
EntityManager (μν°ν° λ§€λμ )
μν°ν°λ₯Ό κ΄λ¦¬νκ³ λ°μ΄ν°λ² μ΄μ€μ μνΈμμ©νλ ν΅μ¬ κ°μ²΄μ
λλ€.
β’
μν°ν°μ μ μ₯, μ‘°ν, μμ , μμ λ±μ μμ
μ μνν©λλ€.
β’
persist(), find(), merge(), remove() λ±μ λ©μλλ₯Ό μ¬μ©νμ¬ μν°ν°λ₯Ό μ‘°μν μ μμ΅λλ€.
β’
μμμ± μ»¨ν
μ€νΈ(PersistenceContext)λ₯Ό ν΅ν΄ μν°ν°μ μνλ₯Ό κ΄λ¦¬ν©λλ€.
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
User user = new User();
user.setName("John");
user.setEmail("john@example.com");
entityManager.persist(user);
entityManager.getTransaction().commit();
entityManager.close();
Java
볡μ¬
@PersistenceContext
private EntityManager entityManager;
Java
볡μ¬
PersistenceContext (μμμ± μ»¨ν
μ€νΈ)
EntityManagerκ° κ΄λ¦¬νλ μν°ν° μ μ₯μλ‘, 1μ°¨ μΊμ μν μ μνν©λλ€.
β’
μν°ν°κ° EntityManagerμ μν΄ κ΄λ¦¬λλ©΄, λ°μ΄ν°λ² μ΄μ€μμ μ‘°νλ μν°ν°κ° μμμ± μ»¨ν
μ€νΈμ μ μ₯λ©λλ€.
β’
λμΌν νΈλμμ
λ΄μμ κ°μ μν°ν°λ₯Ό λ€μ μ‘°ννλ©΄ λ°μ΄ν°λ² μ΄μ€μ μ κ·Όνμ§ μκ³ 1μ°¨ μΊμμμ κ°μ Έμ΅λλ€.
β’
λ³κ²½ κ°μ§(Dirty Checking) κΈ°λ₯μ μ 곡νμ¬, μν°ν°μ κ°μ λ³κ²½νλ©΄ μλμΌλ‘ UPDATE 쿼리λ₯Ό μ€νν©λλ€.
User user = entityManager.find(User.class, 1L); // DBμμ μ‘°ν
user.setName("Updated Name"); // κ° λ³κ²½
// λ³λμ update 쿼리λ₯Ό μ€ννμ§ μμλ λ³κ²½μ΄ κ°μ§λμ΄ μλ λ°μλ¨
entityManager.getTransaction().commit();
Java
볡μ¬
TransactionManager (νΈλμμ
λ§€λμ )
λ°μ΄ν° λ³κ²½μ΄ λ°μν λ νΈλμμ
μ κ΄λ¦¬νλ μν μ μνν©λλ€.
β’
λ°μ΄ν°λ² μ΄μ€μ ACID(μμμ±, μΌκ΄μ±, 격리μ±, μ§μμ±) νΉμ±μ 보μ₯ν©λλ€.
β’
λ°μ΄ν° μ μ₯, μμ , μμ λ±μ μμ
μ λ°λμ νΈλμμ
λ΄μμ μ€νν΄μΌ ν©λλ€.
β’
Spring Bootμμλ @Transactional μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ¬ κ°λ¨ν νΈλμμ
μ κ΄λ¦¬ν μ μμ΅λλ€.
@Service
public class UserService {
@Autowired
private EntityManager entityManager;
@Transactional
public void updateUser(Long id, String newName) {
User user = entityManager.find(User.class, id);
user.setName(newName);
} // νΈλμμ
μ’
λ£ μ μλμΌλ‘ λ³κ²½ μ¬ν λ°μ
}
Java
볡μ¬
DB (Database, λ°μ΄ν°λ² μ΄μ€)
JPAμ μ΅μ’
μ μ₯μλ‘, μν°ν°μ λ°μ΄ν°λ₯Ό μ μ₯νλ 곡κ°μ
λλ€.
β’
JPAκ° SQLμ μλ μμ±νμ¬ λ°μ΄ν°λ² μ΄μ€μ μνΈμμ©ν©λλ€.
β’
DDL(ν
μ΄λΈ μμ±) λ° DML(λ°μ΄ν° μ‘°μ) μμ
μ΄ μνλ©λλ€.
β’
JPA μ€μ μ λ°λΌ Hibernate λλ EclipseLink κ°μ ꡬνμ²΄κ° μ¬μ©λ©λλ€.
INSERT INTO user (name, email) VALUES ('John', 'john@example.com');
UPDATE user SET name = 'Updated Name' WHERE id = 1;
SQL
볡μ¬
μ΅μ’
μμ½
JPAλ κ°μ²΄(Entity)μ λ°μ΄ν°λ² μ΄μ€ ν
μ΄λΈμ μλμΌλ‘ λ§€ννλ ORM κΈ°μ μ
λλ€.
JPAλ EntityManagerλ₯Ό ν΅ν΄ μν°ν°λ₯Ό κ΄λ¦¬νκ³ , νΈλμμ
μ μ²λ¦¬νλ©°, SQLμ μλ μμ±νμ¬ DBμ μ°λνλ ORM νλ μμν¬μ
λλ€.
β’
Persistence Unitμ μ€μ μ μ μνκ³ ,
β’
EntityManagerFactoryλ EntityManagerλ₯Ό μμ±νμ¬ μν°ν°λ₯Ό κ΄λ¦¬ν©λλ€.
β’
PersistenceContextλ μν°ν°μ μνλ₯Ό μΆμ νκ³ , 1μ°¨ μΊμλ₯Ό ν΅ν΄ μ±λ₯μ μ΅μ νν©λλ€.
β’
TransactionManagerλ λ°μ΄ν° λ³κ²½ μ νΈλμμ
μ κ΄λ¦¬νμ¬ μ ν©μ±μ 보μ₯ν©λλ€.
β’
μ΅μ’
μ μΌλ‘ JPAλ λ°μ΄ν°λ² μ΄μ€μ μ°λλμ΄ SQLμ μ€ννκ³ λ°μ΄ν°λ₯Ό κ΄λ¦¬ν©λλ€. 
JPAμ μ₯μ
β’
κ°μ²΄μ§ν₯μ μΈ μ½λ μμ± κ°λ₯
β’
μμ°μ± ν₯μ
β’
μ μ§λ³΄μ μ©μ΄
β’
λ°μ΄ν°λ² μ΄μ€μ λ
립μ μΈ κ°λ° κ°λ₯
JPA vs MyBatis
λΉκ΅ νλͺ© | JPA (Java Persistence API) | MyBatis |
κ°λ
| κ°μ²΄μ κ΄κ³ν λ°μ΄ν°λ² μ΄μ€ κ°μ
λ§€νμ μλννλ ORM κΈ°μ | SQL λ§€ν κΈ°λ°μ
λ°μ΄ν°λ² μ΄μ€ μ κ·Ό νλ μμν¬ |
쿼리 λ°©μ | SQLμ μλ μμ± (JPQL, Criteria API, QueryDSL μ§μ) | SQLμ μ§μ μμ±νμ¬ μ¬μ© (XML λλ μ΄λ
Έν
μ΄μ
νμ©) |
κ°λ° μμ°μ± | CRUD μλν, κ°μ²΄ μ€μ¬ κ°λ°λ‘ μ½λ κ°κ²° | SQLμ μ§μ μμ±ν΄μΌ νλ―λ‘ λ°λ³΅ μ½λ μ¦κ° κ°λ₯ |
μ μ§λ³΄μμ± | μν°ν° μ€μ¬ κ°λ°, λΉμ¦λμ€ λ‘μ§κ³Ό λ°μ΄ν° μ κ·Ό μ½λ λΆλ¦¬ | SQLμ΄ μ½λμ ν¬ν¨λλ―λ‘ λ³κ²½ μ μ μ§λ³΄μ λΆλ΄ μ¦κ° |
νΌν¬λ¨Όμ€ | 1μ°¨ μΊμ, λ³κ²½ κ°μ§, μ§μ° λ‘λ© λ± μ΅μ ν κΈ°λ₯ μ 곡 | 쿼리λ₯Ό μ§μ μ΅μ νν μ μμ΄ μ±λ₯ μ‘°μ μ΄ μ©μ΄ |
νΈλμμ
κ΄λ¦¬ | JPA λ΄λΆμμ νΈλμμ
μλ κ΄λ¦¬ (@Transactional) | MyBatis μ체 νΈλμμ
κ΄λ¦¬ κΈ°λ₯μ μμΌλ©°, Spring νΈλμμ
νμ© |
λμ 쿼리 | Criteria API, QueryDSL μ¬μ© κ°λ₯ | if, choose, foreach λ±μ XML νκ·Έλ‘ μ μ°ν λμ 쿼리 μμ± κ°λ₯ |
μΊμ± κΈ°λ₯ | 1μ°¨ μΊμ(μμμ± μ»¨ν
μ€νΈ) λ° 2μ°¨ μΊμ μ§μ | κΈ°λ³Έμ μΌλ‘ μΊμ± κΈ°λ₯μ΄ μμΌλ©°, λ³λ μ€μ νμ |
μ¬μ© λͺ©μ | λλ©μΈ μ€μ¬ μ€κ³(DDD), λκ·λͺ¨ νλ‘μ νΈμ μ ν© | 볡μ‘ν SQLμ΄ λ§μ μμ€ν
, νΉμ DB μ΅μ νκ° νμν κ²½μ° |
νμ΅ λμ΄λ | ORM κ°λ
νμ΅ νμ, μ΄κΈ° μ§μ
μ₯λ²½μ΄ μμ | SQL μ€μ¬ κ°λ° λ°©μμΌλ‘ λΉκ΅μ μ½κ³ μ΅μν¨ |
JPAμ μ£Όμ κΈ°λ₯
κΈ°λ₯ | μ€λͺ
|
μν°ν°μ ν
μ΄λΈ λ§€ν | μλ° κ°μ²΄μ λ°μ΄ν°λ² μ΄μ€ ν
μ΄λΈμ μλμΌλ‘ λ§€ν |
μμμ± μ»¨ν
μ€νΈ | μν°ν°λ₯Ό μꡬ μ μ₯νλ νκ²½μ μ 곡 |
JPQL | SQLμ μΆμνν κ°μ²΄μ§ν₯ 쿼리 μΈμ΄ μ 곡 |
Criteria API | μλ° μ½λλ‘ JPQLμ μμ±ν μ μκ² λμμ£Όλ λΉλ ν΄λμ€ API |
QueryDSL | νμ
μμ ν SQLκ³Ό κ°μ 쿼리λ₯Ό μλ° μ½λλ‘ μμ±ν μ μκ² ν΄μ£Όλ νλ μμν¬ |