JPA๋? ๊ฐ๋ , ์์์ฑ ์ปจํ ์คํธ, JPQL๊น์ง ํ๋ฒ์ ์ ๋ฆฌ
JPA(Java Persistence API)๋ ์๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ
์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๋๋ก ๋์์ฃผ๋ ORM(Object-Relational Mapping) ๊ธฐ์ ์ด๋ค.
์ฆ, SQL์ ์ง์ ์์ฑํ์ง ์๊ณ ์๋ฐ ๊ฐ์ฒด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ ์ ์๋๋ก ํด์ค๋ค.
โ JPA์ ์ฃผ์ ๊ฐ๋
1. ORM(Object-Relational Mapping)
JPA๋ ORM ๊ธฐ์ ์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฉฐ, ๊ฐ์ฒด์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ๋งคํํ๋ ์ญํ ์ ํ๋ค.
์ด๋ฅผ ํตํด SQL์ ์ง์ ๋ค๋ฃจ์ง ์์๋ ๊ฐ์ฒด๋ฅผ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์กฐํํ ์ ์๋ค.
2. ์ํฐํฐ(Entity)
JPA์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ ์๋ฐ ๊ฐ์ฒด๋ฅผ "์ํฐํฐ"๋ผ๊ณ ํ๋ค.
์ํฐํฐ ํด๋์ค๋ @Entity ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ํ๋ค.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
3. ์์์ฑ ์ปจํ ์คํธ(Persistence Context)
์์์ฑ ์ปจํ ์คํธ๋ JPA์์ ๋งค์ฐ ์ค์ํ ๊ฐ๋ ์ผ๋ก, ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์์ํ(Persistence)ํ์ฌ ๊ด๋ฆฌํ๋ ๊ณต๊ฐ์ด๋ค.
- ์์์ฑ ์ปจํ ์คํธ๋ EntityManager๊ฐ ๊ด๋ฆฌํ๋ค.
- ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅ๋ ์ํฐํฐ๋ ์๋์ผ๋ก ๋ณ๊ฒฝ ๊ฐ์ง๊ฐ ์ด๋ฃจ์ด์ง๋ค.
- ๋์ผํ ํธ๋์ญ์ ๋ด์์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋ 1์ฐจ ์บ์์์ ๊ฐ์ ธ์จ๋ค.
๐ ์ฝ๊ฒ ๋งํด, JPA๊ฐ ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๋ "๋ฉ๋ชจ๋ฆฌ ์ฐฝ๊ณ "๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
User user = new User();
user.setName("Kim");
em.persist(user); // ์์์ฑ ์ปจํ
์คํธ์ ์ ์ฅ
em.getTransaction().commit();
โ JPA์ ์ฃผ์ ๊ธฐ๋ฅ
1. CRUD ์ฐ์ฐ
JPA๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด๋ฅผ ํ์ฉํ์ฌ ์์ฝ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ์ฐ์ ์ํํ ์ ์๋ค.
โ ์ ์ฅํ๊ธฐ (Create)
User user = new User();
user.setName("Kim");
user.setEmail("kim@example.com");
entityManager.persist(user);
โ ์กฐํํ๊ธฐ (Read)
User user = entityManager.find(User.class, 1L);
System.out.println(user.getName());
โ ์์ ํ๊ธฐ (Update)
User user = entityManager.find(User.class, 1L);
user.setName("Lee"); // ๋ณ๊ฒฝ ๊ฐ์ง (Dirty Checking)์ผ๋ก ์๋ ์
๋ฐ์ดํธ๋จ
โ ์ญ์ ํ๊ธฐ (Delete)
User user = entityManager.find(User.class, 1L);
entityManager.remove(user);
โ JPQL(Java Persistence Query Language)์ด๋?
JPQL์ JPA์์ ์ ๊ณตํ๋ ๊ฐ์ฒด ์งํฅ ์ฟผ๋ฆฌ ์ธ์ด์ด๋ค.
SQL๊ณผ ์ ์ฌํ์ง๋ง, ํ ์ด๋ธ์ด ์๋ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
๐ JPQL ์์
โ ์ ์ฒด ์กฐํ
List<User> users = entityManager.createQuery("SELECT u FROM User u", User.class)
.getResultList();
โ ํน์ ์กฐ๊ฑด์ผ๋ก ์กฐํ
User user = entityManager.createQuery("SELECT u FROM User u WHERE u.name = :name", User.class)
.setParameter("name", "Kim")
.getSingleResult();
โ ์ ๋ ฌ ๋ฐ ํ์ด์ง ์ฒ๋ฆฌ
List<User> users = entityManager.createQuery("SELECT u FROM User u ORDER BY u.name DESC", User.class)
.setFirstResult(0)
.setMaxResults(10)
.getResultList();
โ JPA์ ์ฅ์
- ์์ฐ์ฑ ์ฆ๊ฐ: SQL์ ์ง์ ์์ฑํ์ง ์๊ณ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ค.
- ์ ์ง๋ณด์ ์ฉ์ด: ๊ฐ์ฒด ์งํฅ ์ฝ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฝ๋๊ฐ ๋ถ๋ฆฌ๋์ด ์ ์ง๋ณด์๊ฐ ์ฌ์์ง๋ค.
- DB ์ข ์์ฑ ๊ฐ์: ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ข ์๋์ง ์์ผ๋ฉฐ, ๋ค๋ฅธ DB๋ก ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค.
- ์ฑ๋ฅ ์ต์ ํ: 1์ฐจ ์บ์, ์ง์ฐ ๋ก๋ฉ, ๋ฐฐ์น ์ฟผ๋ฆฌ ๋ฑ ๋ค์ํ ์ต์ ํ ๊ธฐ๋ฒ์ ์ง์ํ๋ค.
โ JPA ์ฌ์ฉ ์ ์ฃผ์ํ ์
- ์ฆ์ ๋ก๋ฉ(EAGER) vs ์ง์ฐ ๋ก๋ฉ(LAZY)
- @OneToMany, @ManyToOne ๊ด๊ณ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก LAZY(์ง์ฐ ๋ก๋ฉ)๋ฅผ ์ฌ์ฉํ์ฌ ํ์ํ ๋๋ง ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์ฑ๋ฅ์ ์ข๋ค.
- ์ฆ์ ๋ก๋ฉ์ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ JOIN์ด ๋ฐ์ํ์ฌ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์๋ค.
- ํธ๋์ญ์
๊ด๋ฆฌ
- @Transactional์ ์ฌ์ฉํ์ฌ ํธ๋์ญ์ ์ ๊ด๋ฆฌํด์ผ ํ๋ค.
- ํธ๋์ญ์ ์ด ์์ผ๋ฉด ๋ณ๊ฒฝ ์ฌํญ์ด ์ ์ฉ๋์ง ์๋๋ค.
- JPQL๊ณผ Native Query ์ฐจ์ด
- JPQL์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์คํ๋๋ฏ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฆฝ์ฑ์ด ๋๋ค.
- Native Query๋ SQL์ ์ง์ ์คํํ๋ ๋ฐฉ์์ผ๋ก, ํน์ DB์ ์ข ์๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
๐ฅ ๋ง์น๋ฉฐ
JPA๋ ์๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๋๋ก ๋์์ฃผ๋ ๊ฐ๋ ฅํ ๋๊ตฌ๋ค.
์์์ฑ ์ปจํ ์คํธ์ JPQL์ ์ดํดํ๋ฉด ๋์ฑ ํจ์จ์ ์ผ๋ก JPA๋ฅผ ํ์ฉํ ์ ์๋ค.