๐Ÿ—จ๏ธ Backend/Java

JPA๋ž€? ๊ฐœ๋…, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ, JPQL๊นŒ์ง€ ํ•œ๋ฒˆ์— ์ •๋ฆฌ

Kyle99 2025. 3. 6. 02:21

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์˜ ์žฅ์ 

  1. ์ƒ์‚ฐ์„ฑ ์ฆ๊ฐ€: SQL์„ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  2. ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด: ๊ฐ์ฒด ์ง€ํ–ฅ ์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฝ”๋“œ๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค.
  3. DB ์ข…์†์„ฑ ๊ฐ์†Œ: ํŠน์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ข…์†๋˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹ค๋ฅธ DB๋กœ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  4. ์„ฑ๋Šฅ ์ตœ์ ํ™”: 1์ฐจ ์บ์‹œ, ์ง€์—ฐ ๋กœ๋”ฉ, ๋ฐฐ์น˜ ์ฟผ๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์ง€์›ํ•œ๋‹ค.

โœ… JPA ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 

  1. ์ฆ‰์‹œ ๋กœ๋”ฉ(EAGER) vs ์ง€์—ฐ ๋กœ๋”ฉ(LAZY)
    • @OneToMany, @ManyToOne ๊ด€๊ณ„์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ LAZY(์ง€์—ฐ ๋กœ๋”ฉ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์— ์ข‹๋‹ค.
    • ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ JOIN์ด ๋ฐœ์ƒํ•˜์—ฌ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.
  2. ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ
    • @Transactional์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
    • ํŠธ๋žœ์žญ์…˜์ด ์—†์œผ๋ฉด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
  3. JPQL๊ณผ Native Query ์ฐจ์ด
    • JPQL์€ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์‹คํ–‰๋˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋…๋ฆฝ์„ฑ์ด ๋†’๋‹ค.
    • Native Query๋Š” SQL์„ ์ง์ ‘ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, ํŠน์ • DB์— ์ข…์†๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค.

๐Ÿ”ฅ ๋งˆ์น˜๋ฉฐ

JPA๋Š” ์ž๋ฐ” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ JPQL์„ ์ดํ•ดํ•˜๋ฉด ๋”์šฑ ํšจ์œจ์ ์œผ๋กœ JPA๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.