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๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ์๋ฐ ์ฝ๋๋ก ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ํ๋ ์์ํฌ |