์ƒˆ์†Œ์‹

Back-End/JPA

[JPA] JPA (Java Persistence API) ?!

  • -

 

 

 

 

 

 

์˜ค๋Š˜์€ JPA (Java Persistence API)๋ž€ ๋ฌด์—‡์ธ์ง€ ํ•œ๋ฒˆ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜๋„ ๊ทธ๋Ÿผ ๊ฐ™์ด ๊ณต๋ถ€๋ฅผ ํ•ด๋ณผ๊นŒ์š”?

 

 

 


#1. JPA ?!

JPA (Java Persistence API)๋Š” ์ž๋ฐ”์—์„œ ORM(Object-Relational Mapping)์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ API์ด๋ฉฐ, ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ„์˜ ๋ถˆ์ผ์น˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.

 

JPA์˜ ๊ธฐ๋ณธ ๋ฌธ๋ฒ• ๋ฐ ํ™œ์šฉ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

 


#2. JPA ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

 

 

#2. 1. ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ์ž‘์„ฑ

JPA๋Š” ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

@Entity
@Table(name = "table_name")
public class EntityName {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "column_name")
    private String columnName;

    // getter, setter, constructor ๋“ฑ
}
  • @Entity: ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์—”ํ‹ฐํ‹ฐ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • @Table(name = "table_name"): ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๊ฐ€ ๋งคํ•‘๋  ํ…Œ์ด๋ธ”์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • @Id: ์—”ํ‹ฐํ‹ฐ์˜ ๊ธฐ๋ณธ ํ‚ค(primary key)๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • @GeneratedValue(strategy = GenerationType.IDENTITY): ๊ธฐ๋ณธ ํ‚ค ๊ฐ’์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • @Column(name = "column_name"): ํ•„๋“œ๊ฐ€ ๋งคํ•‘๋  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋ช…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

 

 

#2. 2. EntityManager ์ƒ์„ฑ

EntityManager๋Š” JPA์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฐ์ฒด๋กœ, ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. EntityManager๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence-unit-name");
EntityManager em = emf.createEntityManager();
  • Persistence.createEntityManagerFactory("persistence-unit-name"): persistence.xml ํŒŒ์ผ์—์„œ ์ •์˜ํ•œ persistence-unit์˜ ์ด๋ฆ„์„ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ EntityManagerFactory๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • emf.createEntityManager(): EntityManagerFactory๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ EntityManager๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

 

#2. 3. ์—”ํ‹ฐํ‹ฐ ์ €์žฅ

EntityManager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

EntityTransaction tx = em.getTransaction();
tx.begin();

em.persist(entity);

tx.commit();
  • em.getTransaction(): ํ˜„์žฌ EntityManager์˜ EntityTransaction์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • tx.begin(): ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • em.persist(entity): ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • tx.commit(): ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค.

 

 

#2. 4. ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ

EntityManager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

EntityTransaction tx = em.getTransaction();
tx.begin();

EntityName entity = em.find(EntityName.class, id);

tx.commit();
  • em.find(EntityName.class, id): ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์™€ ๊ธฐ๋ณธ ํ‚ค ๊ฐ’์„ ์ „๋‹ฌํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

 

 

#2. 5. ์—”ํ‹ฐํ‹ฐ ์ˆ˜์ •

EntityManager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

EntityTransaction tx = em.getTransaction();
tx.begin();

EntityName entity = em.find(EntityName.class, id);
entity.setColumnName("new value");

tx.commit();
  • em.find(EntityName.class, id): ์ˆ˜์ •ํ•  ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
  • entity.setColumnName("new value"): ํ•„๋“œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ€๊ฒฝ๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•  ๋•Œ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.

 

 

#2. 6. ์—”ํ‹ฐํ‹ฐ ์‚ญ์ œ

EntityManager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

EntityTransaction tx = em.getTransaction();
tx.begin();

EntityName entity = em.find(EntityName.class, id);
em.remove(entity);

tx.commit();
  • em.remove(entity): ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

 

 

 


#3. JPA ํ™œ์šฉ ๋ฐฉ๋ฒ•

JPA๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ์‚ฐ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

#3. 1. ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰

JPA๋Š” ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์˜ ๊ด€๊ณ„๋ฅผ ์ž๋™์œผ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

EntityName entity = em.find(EntityName.class, id);
entity.getRelatedEntity().getRelatedField();

 

 

#3. 2. JPQL

JPQL (Java Persistence Query Language)์€ JPA์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. JPQL์„ ์‚ฌ์šฉํ•˜๋ฉด SQL๊ณผ ์œ ์‚ฌํ•œ ๊ตฌ๋ฌธ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TypedQuery<EntityName> query = em.createQuery("SELECT e FROM EntityName e WHERE e.columnName = :columnName", EntityName.class);
query.setParameter("columnName", "value");
List<EntityName> results = query.getResultList();
  • em.createQuery("JPQL", EntityName.class): JPQL์„ ์‚ฌ์šฉํ•˜์—ฌ ์กฐํšŒํ•  ์—”ํ‹ฐํ‹ฐ์™€ ๋ฐ˜ํ™˜ํ•  ํƒ€์ž…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • query.setParameter("columnName", "value"): JPQL์—์„œ ์‚ฌ์šฉํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ’์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • query.getResultList(): ์กฐํšŒ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

 

 

 


#4. ์ž˜๋ชป๋œ JPA ์‚ฌ์šฉ๋ฒ•

JPA๋ฅผ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ๋ฐ์ดํ„ฐ ๋ถˆ์ผ์น˜ ๋“ฑ์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

#4. 1. N+1 ๋ฌธ์ œ

N+1 ๋ฌธ์ œ๋Š” ์—”ํ‹ฐํ‹ฐ์™€ ๊ด€๋ จ๋œ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฟผ๋ฆฌํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์‹œ๊ธ€ ์—”ํ‹ฐํ‹ฐ์™€ ๋Œ“๊ธ€ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์žˆ์„ ๋•Œ, ๊ฒŒ์‹œ๊ธ€์„ ์กฐํšŒํ•˜๋ฉด์„œ ๋Œ“๊ธ€์„ ํ•จ๊ป˜ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ, ๊ฒŒ์‹œ๊ธ€์˜ ๊ฐœ์ˆ˜๋งŒํผ ๋Œ“๊ธ€ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” FetchType.LAZY๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

#4. 2. Cascade ์„ค์ • ๋ฌธ์ œ

Cascade๋Š” ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๋œ ์ž์‹ ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์ž๋™์œผ๋กœ ์ „ํŒŒํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Cascade๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

#4. 3. ์ง€์—ฐ ๋กœ๋”ฉ(Lazy Loading) ๋ฌธ์ œ

์ง€์—ฐ ๋กœ๋”ฉ์€ ํ•„์š”ํ•œ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ง€์—ฐ ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ๋งค๋ฒˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด FetchType.EAGER๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฆ‰์‹œ ๋กœ๋”ฉํ•˜๊ฑฐ๋‚˜, Batch Size๋ฅผ ์„ค์ •ํ•˜์—ฌ ์ผ๊ด„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

#4. 4. ์„ฑ๋Šฅ ๋ฌธ์ œ

JPA๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์ด์—์„œ ๋งคํ•‘ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ถ€ ์ž‘์—…์—์„œ๋Š” SQL ์ง์ ‘ ์‹คํ–‰๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์บ์‹œ ์„ค์ • ๋“ฑ์„ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 


๋งˆ์น˜๋ฉฐ..

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

 

 

 

 

'Back-End > JPA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Error] JPA Cannot resolve table  (0) 2023.02.04
Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Š

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๐Ÿ‘