๐Ÿง‘๐Ÿปโ€๐Ÿ’ปJPA(Java Persistence API)

DEVJUNยท2022๋…„ 2์›” 6์ผ
0

JPA

๋ชฉ๋ก ๋ณด๊ธฐ
1/1

1. JPA๋ž€?
2. SQL ์ค‘์‹ฌ ๊ฐœ๋ฐœ์˜ ๋ฌธ์ œ์ 
3. JPA(Java Persistence API) ์‚ฌ์šฉ์ด์œ 

1. JPA๋ž€?

JPA๋Š” ์ž๋ฐ” ์ง„์˜์˜ ORM(Object-relational mapping)๊ธฐ์ˆ  ํ‘œ์ค€์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ์Œ์ด๋‹ค. ORM์€ ๊ฐ์ฒด๋Š” ๊ฐ์ฒด๋Œ€๋กœ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Œ€๋กœ ์„ค๊ณ„ํ•˜์—ฌ ORM ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ค‘๊ฐ„์—์„œ ๊ทธ ๋‘˜์„ ๋งคํ•‘ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. Spring Boot์™€ ๊ฐ™์ด ์›น์„œ๋ฒ„ ๊ฐœ๋ฐœ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋Š” Node Express์—์„œ๋Š” Sequelize๊ฐ€ ORM์ธ ์…ˆ์ด๋‹ค.

JPA๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ JDBC์‚ฌ์ด์—์„œ ๋™์ž‘ํ•œ๋‹ค. JDBC(Java Database Connectivity)๋Š” ์ž๋ฐ”์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ž๋ฐ” API์ด๋‹ค.

์œ„์—์„œ JPA๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ์Œ์ด๋ผ๊ณ  ํ‘œํ˜„ํ–ˆ๋‹ค. JPA 2.1 ํ‘œ์ค€ ๋ช…์„ธ๋ฅผ ๊ตฌํ˜„ํ•œ 3๊ฐ€์ง€ ๊ตฌํ˜„์ฒด๋กœ๋Š” Hibernate, EclipseLink, DataNucleus๊ฐ€ ์žˆ๋‹ค.

2. SQL ์ค‘์‹ฌ ๊ฐœ๋ฐœ์˜ ๋ฌธ์ œ์ 

JPA๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋กœ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

1. ๋ฌดํ•œ ๋ฐ˜๋ณต, ์ง€๋ฃจํ•œ ์ฝ”๋“œ

SQL ์ค‘์‹ฌ์ ์ธ ๊ฐœ๋ฐœ์„ ํ•  ๊ฒฝ์šฐ ์ฝ”๋“œ๊ฐ€ ๋ฌดํ•œ ๋ฐ˜๋ณต, ์ง€๋ฃจํ•œ ์ฝ”๋“œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž!


public class Member{
	private String memberId;
	private String name;
}

ํšŒ์›์— ๊ด€ํ•œ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค. ํšŒ์› ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋””๋น„์— ์ €์žฅ ๋ฐ ์ˆ˜์ •, ์กฐํšŒ, ์‚ญ์ œ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„  ์ฟผ๋ฆฌ๋ฌธ์ด ๊ณ„์†ํ•ด์„œ ๋ฐ˜๋ณต๋  ๊ฒƒ์ด๊ณ  ๊ฐœ๋ฐœ์ž๋Š” ์ˆ˜๋งŽ์€ ์ฟผ๋ฆฌ๋ฌธ์„ ๋ฐ˜๋ณต ์ž‘์„ฑํ•ด์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋‹นํžˆ ๊ท€์ฐฎ๊ณ  ํ”ผ๊ณคํ•  ๊ฒƒ์ด๋‹ค...๐Ÿ˜ฎโ€๐Ÿ’จ

INSERT INTO MEMBER(MEMBER_ID, NAME) VALUES 
SELECT MEMBER_ID, NAME FROM MEMBER M
UPDATE MEMBER SET ...

2. ๊ฐ์ฒด ์ง€ํ–ฅ๊ณผ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ถˆ์ผ์น˜

ํŒจ๋Ÿฌ๋‹ค์ž„์ด ๋‹ค๋ฅธ ๋‘ ๊ฐ€์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์–ต์ง€๋กœ ๋งคํ•‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. Object๋ฅผ RDB์— ๋„ฃ์œผ๋ ค๊ณ  ํ•˜๋‹ˆ๊นŒ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
ํ•˜์ง€๋งŒ, RDB๊ฐ€ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ SQL๋ฟ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ, Object๋ฅผ SQL๋กœ ์งœ์•ผํ•œ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ SQL๋งคํผ๊ฐ€ ๋˜์–ด ์ˆ˜๋งŽ์€ SQL ์ž‘์—…์„ ํ•˜๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

3. ๊ฐ์ฒด(Object)์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(RDB)์˜ ์ฐจ์ด

๊ฐ์ฒด์—๋Š” ์ƒ์†๊ด€๊ณ„๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ RDB์—๋Š” ์ƒ์†๊ด€๊ณ„๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
๋‹ค๋งŒ ์Šˆํผํƒ€์ž…๊ณผ ์„œ๋ธŒํƒ€์ž…์ด ์กด์žฌํ•  ๋ฟ์ด๋‹ค.

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ํ†ตํ•ด ์˜ˆ๋ฅผ ๋“ค์ž๋ฉด ALBUM์„ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„  ITEM๊ณผ ALBUM์„ JOINํ•ด์„œ ์กฐํšŒํ•ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„  ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ชจ๋“  ํ•„๋“œ๊ฐ’์„ ์„ธํŒ…ํ•œ๋‹ค.Item๊ณผ Album ๊ฐ๊ฐ ๋ชจ๋“  ํ•„๋“œ๊ฐ’์„ ์„ธํŒ…ํ•œ๋‹ค. MOVIE, BOOK์— ๋Œ€ํ•œ CRUD ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋„ ๋˜‘๊ฐ™์€ ๋ณต์žกํ•˜๊ณ  ๋ฐ˜๋ณต๋˜๋Š” ๊ณผ์ •์ด ๊ณ„์†๋  ๊ฒƒ์ด๋‹ค....๐Ÿ˜ตโ€๐Ÿ’ซ

4. ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰๋ฌธ์ œ

๊ฐ์ฒด๋Š” ์ž์œ ๋กญ๊ฒŒ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ, ์„œ๋น„์Šค ๋กœ์ง์—์„œ RDB์™€ ์—ฐ๊ฒฐ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํƒ์ƒ‰ํ•  ๋•Œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์—†๋‹ค.
์ฒ˜์Œ ์‹คํ–‰ํ•˜๋Š” SQL์— ๋”ฐ๋ผ ํƒ์ƒ‰ ๋ฒ”์œ„๊ฐ€ ๊ฒฐ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


class Member { 
    String id;        // MEMBER_ID ์ปฌ๋Ÿผ ์‚ฌ์šฉ 
    Team team;        // ์ฐธ์กฐ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค. //** 
    String username;  // USERNAME ์ปฌ๋Ÿผ ์‚ฌ์šฉ 
                     
    Team getTeam() { 
        return team; 
    } 
}

class Team { 
    Long id;         // TEAM_ID PK ์‚ฌ์šฉ 
    String name;     // NAME ์ปฌ๋Ÿผ ์‚ฌ์šฉ 
}
์ฒ˜์Œ SQL์—์„œ Member์™€ Team์„ ๊ฐ€์ ธ์™”๋‹ค๊ณ  ํ•˜๋ฉด, Order๋Š” ๊ฐ€์ ธ์˜ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— 
member.getOrder(); ์€ null ๊ฐ’์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

SELECT M.*, T.* FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID

member.getTeam(); //OK 
member.getOrder(); //null

5. ์—”ํ‹ฐํ‹ฐ ์‹ ๋ขฐ๋ฌธ์ œ


class MemberService {
...
  public void process() {
      Member member = memberDAO.find(memberId);
      member.getTeam(); //???
      member.getOrder().getDelivery(); // ???
  }
}

DAO์—์„œ ์ง์ ‘ ์–ด๋–ค ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ธ๋Š”์ง€ ํ™•์ธํ•˜์ง€ ์•Š๋Š” ์ด์ƒ, ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ง„์ •ํ•œ ์˜๋ฏธ์˜ ๊ณ„์ธต ๋ถ„ํ• ์ด ์–ด๋ ต๋‹ค.

์ •๋ฆฌํ•ด๋ณด๋ฉด ๊ฐ์ฒด๋‹ต๊ฒŒ ๋ชจ๋ธ๋ง ํ• ์ˆ˜๋ก ๋งคํ•‘ ์ž‘์—…๋งŒ ๋Š˜์–ด๋‚œ๋‹ค.
๊ฐ์ฒด๋ฅผ ์ž๋ฐ” ์ปฌ๋ ‰์…˜์— ์ €์žฅ ํ•˜๋“ฏ์ด DB์— ์ €์žฅํ•  ์ˆ˜๋Š” ์—†์„๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ๋‚˜์˜จ ๊ฒฐ๊ณผ๊ฐ€ JPA(Java Persistence API)์ธ ๊ฒƒ์ด๋‹ค!

3. JPA(Java Persistence API) ์‚ฌ์šฉ์ด์œ 

1. SQL ์ค‘์‹ฌ์ ์ธ ๊ฐœ๋ฐœ์—์„œ ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ๊ฐœ๋ฐœ

์œ„์—์„œ SQL ์ค‘์‹ฌ์œผ๋กœ ๊ฐœ๋ฐœํ–ˆ์„ ๋•Œ์˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฌธ์ œ์ ์„ ๋ณด์•˜๋‹ค JPA๋Š” ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

2. ์ƒ์‚ฐ์„ฑ

SQL ์ค‘์‹ฌ์—์„œ ๊ฐœ๋ฐœํ•  ๊ฒฝ์šฐ ์ˆ˜ ๋งŽ์€ SQL๋ฌธ์„ ์ž‘์„ฑํ•ด์•ผ ํ–ˆ๋‹ค ํ•˜์ง€๋งŒ JPA ์‚ฌ์šฉ์‹œ

โ€ข ์ €์žฅ: jpa.persist(member)
โ€ข ์กฐํšŒ: Member member = jpa.find(memberId)
โ€ข ์ˆ˜์ •: member.setName(โ€œ๋ณ€๊ฒฝํ•  ์ด๋ฆ„โ€)
โ€ข ์‚ญ์ œ: jpa.remove(member)

์œ„์™€ ๊ฐ™์ด ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ CRUD๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ์œ ์ง€๋ณด์ˆ˜

๊ธฐ์กด์— ํ•„๋“œ ๋ณ€๊ฒฝ์‹œ ๋ชจ๋“  SQL๋ฌธ์„ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ JPA์‚ฌ์šฉ์‹œ ํ•„๋“œ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋˜๊ณ , SQL์€ JPA๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค.

4. JPA์™€ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๋ถˆ์ผ์น˜ ํ•ด๊ฒฐ

  • 1.JPA์™€ ์ƒ์†

    ๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ALBUM ์ €์žฅ์‹œ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„๋‹จํ•œ ์ž‘์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • 2.JPA์™€ ์—ฐ๊ด€๊ด€๊ณ„

    ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋กœ ์—ฐ๊ด€๊ด€๊ณ„ ์ €์žฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • 3.JPA์™€ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰

    ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ์™„์ „ํžˆ ์ž์œ ๋กญ๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
    ์ง€์—ฐ ๋กœ๋”ฉ ์ „๋žต(Lazy Loading) ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋‹ค.
    ๊ด€๋ จ๋œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ทธ ์‹œ์ ์— SELECT Query๋ฅผ ๋‚ ๋ ค์„œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ „๋žต์ด๋‹ค.

  • 4.JPA์™€ ๋น„๊ตํ•˜๊ธฐ

    ๋™์ผํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ๋Š” ๊ฐ™์Œ์„ ๋ณด์žฅํ•œ๋‹ค.
  String memberId = "100"; 
  Member member1 = jpa.find(Member.class, memberId); // DB์—์„œ ๊ฐ€์ ธ์˜ด 
  Member member2 = jpa.find(Member.class, memberId); // 1์ฐจ ์บ์‹œ์—์„œ ๊ฐ€์ ธ์˜ด
  member1 == member2; //๊ฐ™๋‹ค.

5. JPA์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋Šฅ

  1. 1์ฐจ ์บ์‹œ์™€ ๋™์ผ์„ฑ ๋ณด์žฅ
String memberId = "100";
Member m1 = jpa.find(Member.class, memberId); //SQL
Member m2 = jpa.find(Member.class, memberId); //์บ์‹œ
println(m1 == m2) //true
  1. ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ๋Š” ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋Š” sql๋ฌธ์„ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰ํ•จ์œผ๋กœ ์•ฝ๊ฐ„์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ์ด ์žˆ๋‹ค.

  2. DB Isolation Level์ด Read Commit์ด์–ด๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Repeatable Read ๋ณด์žฅํ•œ๋‹ค.

  1. ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ์“ฐ๊ธฐ ์ง€์—ฐ
  • Insert
transaction.begin(); // [ํŠธ๋žœ์žญ์…˜] ์‹œ์ž‘
 
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);

//์—ฌ๊ธฐ๊นŒ์ง€ INSERT SQL์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ณด๋‚ด์ง€ ์•Š๋Š”๋‹ค.
//์ปค๋ฐ‹ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— INSERT SQL์„ ๋ชจ์•„์„œ ๋ณด๋‚ธ๋‹ค.
transaction.commit(); // [ํŠธ๋žœ์žญ์…˜] ์ปค๋ฐ‹
  1. ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•  ๋•Œ๊นŒ์ง€ INSERT SQL์„ ๋ชจ์€๋‹ค. - (ํ•œ๋ฒˆ์— ๋ณด๋‚ด๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ ํƒ€๋Š” ํšŸ์ˆ˜๋ฅผ ์ค„์—ฌ์ค€๋‹ค)
  2. JDBC BATCH SQL ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์„œ ํ•œ๋ฒˆ์— SQL ์ „์†กํ•œ๋‹ค.

  • update
transaction.begin(); // [ํŠธ๋žœ์žญ์…˜] ์‹œ์ž‘
 
changeMember(memberA);
deleteMember(memberB);
๋น„์ฆˆ๋‹ˆ์Šค_๋กœ์ง_์ˆ˜ํ–‰(); //๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰ ๋™์•ˆ DB ๋กœ์šฐ ๋ฝ์ด ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.

//์ปค๋ฐ‹ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— UPDATE, DELETE SQL์„ ๋ณด๋‚ธ๋‹ค.
transaction.commit(); // [ํŠธ๋žœ์žญ์…˜] ์ปค๋ฐ‹
  1. UPDATE, DELETE๋กœ ์ธํ•œ ๋กœ์šฐ(ROW)๋ฝ ์‹œ๊ฐ„์„ ์ตœ์†Œํ™”ํ•œ๋‹ค.
  2. ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ์‹œ UPDATE, DELETE SQL ์‹คํ–‰ํ•˜๊ณ , ๋ฐ”๋กœ ์ปค๋ฐ‹ํ•œ๋‹ค.


    3.์ง€์—ฐ ๋กœ๋”ฉ๊ณผ ์ฆ‰์‹œ ๋กœ๋”ฉ
  • ์ง€์—ฐ๋กœ๋”ฉ:๊ฐ์ฒด๊ฐ€ ์‹ค์ œ ์‚ฌ์šฉ๋  ๋•Œ ๋กœ๋”ฉ
  • ์ฆ‰์‹œ ๋กœ๋”ฉ: JOIN SQL๋กœ ํ•œ๋ฒˆ์— ์—ฐ๊ด€๋œ ๊ฐ์ฒด๊นŒ์ง€ ๋ฏธ๋ฆฌ ์กฐํšŒ

์ถœ์ฒ˜

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

profile
๐Ÿง‘๐Ÿปโ€๐Ÿ’ปiOS

0๊ฐœ์˜ ๋Œ“๊ธ€