Server๐Ÿงค/JPA

[JPA] ํ”„๋ก์‹œ

yujindonut 2023. 2. 24. 12:53
728x90

ํ”„๋ก์‹œ?

Member ์—”ํ‹ฐํ‹ฐ์™€ Team ์—”ํ‹ฐํ‹ฐ๋Š” @Many(Member)ToOne(Team) ๊ด€๊ณ„์— ์žˆ๋‹ค.

 

Member๋ฅผ ์กฐํšŒํ• ๋•Œ, Team์„ ํ•ญ์ƒ ์กฐํšŒํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด? - ๋‚ญ๋น„๊ฐ€ ์—„์ฒญ๋‚˜๊ฒŒ ๋ฐœ์ƒํ•œ๋‹ค.

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ํ•ญ์ƒ Team์„ ์กฐํšŒํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ์ด์œ ๋Š” ์—†๋‹ค!

JPA๋Š” ์ด ๋‚ญ๋น„๋ฅผ ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด, ์ง€์—ฐ๋กœ๋”ฉ๊ณผ ํ”„๋ก์‹œ๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.


์ง€์—ฐ๋กœ๋”ฉ

JPA์—๋Š” em.find()์™€ em.getReference()๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

em.find() : DB๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์กฐํšŒ

em.getReference() : DB์˜ ์กฐํšŒ๋ฅผ ๋ฏธ๋ฃจ๋Š” ๊ฐ€์งœ(ํ”„๋ก์‹œ) ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์กฐํšŒ

 

Member ์—”ํ‹ฐํ‹ฐ

@Entity
@Getter
@Setter
public class Member extends BaseEntity {
โ€‹
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
โ€‹
   @Column(name = "name")
   private String username;
โ€‹
   private Integer age;
โ€‹
   @Enumerated(EnumType.STRING)
   private RoleType roleType;
โ€‹
   @Lob
   private String description;
โ€‹
   @ManyToOne
   @JoinColumn(name = "team_id")
   private Team team;
โ€‹
   @OneToOne
   @JoinColumn(name = "locker_id")
   private Locker locker;
โ€‹
   @OneToMany(mappedBy = "member")
   private List<MemberProduct> memberProducts = new ArrayList<>();
}

 

em.find()๋กœ ๋ฉค๋ฒ„๋ฅผ ์กฐํšŒํ•˜๋ฉด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ”๋กœ ๋‚˜๊ฐ„๋‹ค.

 

Member member = new Member();
member.setCreatedBy("creator");
โ€‹
em.persist(member);
โ€‹
em.flush();
em.clear();
โ€‹
Member findMember = em.find(Member.class, member.getId());
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.username = " + findMember.getUsername());
โ€‹
tx.commit();

 

๊ฒฐ๊ณผ 

Hibernate:
   /* insert hello.jpa.Member
       */ insert
       into
          Member
          (id, createdBy, createdDate, lastModifiedBy, lastModifiedDate, age, description, locker_id, roleType, name)
       values
          (null, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
   select
      member0_.id as id1_4_0_,
      member0_.createdBy as createdB2_4_0_,
      member0_.createdDate as createdD3_4_0_,
      member0_.lastModifiedBy as lastModi4_4_0_,
      member0_.lastModifiedDate as lastModi5_4_0_,
      member0_.age as age6_4_0_,
      member0_.description as descript7_4_0_,
      member0_.locker_id as locker_10_4_0_,
      member0_.roleType as roleType8_4_0_,
      member0_.team_id as team_id11_4_0_,
      member0_.name as name9_4_0_,
      locker1_.id as id1_3_1_,
      locker1_.name as name2_3_1_,
      team2_.id as id1_8_2_,
      team2_.createdBy as createdB2_8_2_,
      team2_.createdDate as createdD3_8_2_,
      team2_.lastModifiedBy as lastModi4_8_2_,
      team2_.lastModifiedDate as lastModi5_8_2_,
      team2_.name as name6_8_2_
   from
      Member member0_
  left outer join
      Locker locker1_
           on member0_.locker_id=locker1_.id
  left outer join
      Team team2_
           on member0_.team_id=team2_.id
   where
      member0_.id=?
findMember.id = 1
findMember.username = creator

 

๋ฐ˜๋Œ€๋กœ, em.getReference()๋กœ ๋ฉค๋ฒ„๋ฅผ ์กฐํšŒํ•˜๋ฉด, ํ•„์š”ํ•œ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ„๋‹ค.

findMember.usernameํ•„๋“œ๋ฅผ ์ถœ๋ ฅํ•  ์‹œ์ ์— DB๋ฅผ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๊ฒŒ ๋œ๋‹ค.

findMember.getClass()๋กœ ๊ฐ์ฒด๋ฅผ ํ™•์ธํ•˜๋ฉด, Member๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ, ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๊ฐ€ ๊ฐ•์ œ๋กœ ๋งŒ๋“  ๊ฐ€์งœ ํด๋ž˜์Šค(HibernateProxy) ๊ฐ์ฒด์ด๋‹ค.

Member member = new Member();
member.setUsername("creator");
โ€‹
em.persist(member);
โ€‹
em.flush();
em.clear();
โ€‹
Member findMember = em.getReference(Member.class, member.getId());
System.out.println("findMember = " + findMember.getClass());
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.username = " + findMember.getUsername());
โ€‹
tx.commit();

 

 

Hibernate:
   /* insert hello.jpa.Member
       */ insert
       into
          Member
          (id, createdBy, createdDate, lastModifiedBy, lastModifiedDate, age, description, locker_id, roleType, name)
       values
          (null, ?, ?, ?, ?, ?, ?, ?, ?, ?)
findMember = class hello.jpa.Member$HibernateProxy$yJgMgbkR
findMember.id = 1
Hibernate:
   select
      member0_.id as id1_4_0_,
      member0_.createdBy as createdB2_4_0_,
      member0_.createdDate as createdD3_4_0_,
      member0_.lastModifiedBy as lastModi4_4_0_,
      member0_.lastModifiedDate as lastModi5_4_0_,
      member0_.age as age6_4_0_,
      member0_.description as descript7_4_0_,
      member0_.locker_id as locker_10_4_0_,
      member0_.roleType as roleType8_4_0_,
      member0_.team_id as team_id11_4_0_,
      member0_.name as name9_4_0_,
      locker1_.id as id1_3_1_,
      locker1_.name as name2_3_1_,
      team2_.id as id1_8_2_,
      team2_.createdBy as createdB2_8_2_,
      team2_.createdDate as createdD3_8_2_,
      team2_.lastModifiedBy as lastModi4_8_2_,
      team2_.lastModifiedDate as lastModi5_8_2_,
      team2_.name as name6_8_2_
   from
      Member member0_
  left outer join
      Locker locker1_
           on member0_.locker_id=locker1_.id
  left outer join
      Team team2_
           on member0_.team_id=team2_.id
   where
      member0_.id=?
findMember.username = creator

 


ํ”„๋ก์‹œ ํŠน์ง•

 

์‹ค์ œ ํด๋ž˜์Šฌ๋ฅผ ์ƒ์† ๋ฐ›์•„์„œ ๋งŒ๋“ค์–ด์ง„๋‹ค. (๊ฒ‰๋ชจ์–‘์ด ๊ฐ™๋‹ค)

์‚ฌ์šฉํ•˜๋Š” ์ž…์žฅ์—์„œ, ์ง„์งœ ๊ฐ์ฒด์ธ์ง€ ํ”„๋ก์‹œ ๊ฐ์ฒด์ธ์ง€ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์‹ค์ œ ๊ฐ์ฒด์˜ ์ฐธ์กฐ(target)์„ ๋ณด๊ด€ํ•œ๋‹ค.

ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.


ํ”„๋ก์‹œ ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™”

Member member = em.getReference(Member.class, “id1”); 
member.getName();

1. em.getReference()๋กœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ, getName() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ

2. MemberProxy๊ฐ์ฒด์— target๊ฐ’์ด ์ฒ˜์Œ์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. JPA๊ฐ€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ดˆ๊ธฐํ™” ์š”์ฒญ์„ ํ•œ๋‹ค.

3. ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ DB์— ์กฐํšŒํ•ด์„œ ์‹ค์ œ Entity๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

4. ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” target(์‹ค์ œ Member Entity)์˜ getName()์„ ํ˜ธ์ถœํ•ด์„œ member.getName()์„ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

5. ํ”„๋ก์‹œ ๊ฐ์ฒด์— target์ด ํ• ๋‹น๋˜๊ณ  ๋‚˜๋ฉด, ๋”์ด์ƒ ํ”„๋ก์‹œ ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™” ๋™์ž‘์€ ์—†์–ด๋„ ๋จ.


ํ”„๋ก์‹œ ํŠน์ง• ์ •๋ฆฌ

  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ, ํ•œ๋ฒˆ๋งŒ ์ดˆ๊ธฐํ™”
  • ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™” ํ• ๋•Œ, ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ๋กœ ์—”ํ‹ฐํ‹ฐ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.
    • ์ดˆ๊ธฐํ™” ๋˜๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒƒ
    • target์— ๊ฐ’์ด ์ฑ„์›Œ์ง€๋Š” ๊ฒƒ
  • ํ”„๋ก์‹œ ๊ฐ์ฒด์™€ ์›๋ณธ ๊ฐ์ฒด๊ฐ€ ํƒ€์ž…์ด ๋‹ค๋ฅด๋‹ค. ํƒ€์ž… ์ฒดํฌ์‹œ ์ฃผ์˜ํ•ด์•ผํ•œ๋‹ค. == ๋น„๊ต X, instanceOf ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•จ
Member find = em.find(Member.class, member1.getId());
Member reference = em.getReference(Member.class, member2.getId());
System.out.println("m1 == m2 : " + (m1 == m2)); 					// false

System.out.println("find : " + (find instanceof Member)); 			// true
System.out.println("reference : " + (reference instanceof Member));	// true

 

  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ฐพ๋Š” ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด, em.getReference()๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 
    • JPA๋Š” ํ•˜๋‚˜์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ์กฐํšŒํ•˜๋Š” ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ์˜ ๋™์ผ์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค.
    • em.getReference()๋กœ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ตณ์ด ๊ฐ€์ ธ์˜ค์ง€ ์•Š๋Š”๋‹ค
Member find = em.find(Member.class, member.getId());
Member reference = em.getReference(Member.class, member.getId());
โ€‹
System.out.println("find == reference : " + (find == reference)); // true

 

  • ๋‘˜๋‹ค getReference()๋กœ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋œ๋‹ค๋ฉด
    • ๋‘˜๋‹ค ๊ฐ™์€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์กฐํšŒ. 
    • JPA๋Š” ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ์กฐํšŒํ•˜๋Š” ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ์˜ ๋™์ผ์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. ํ”„๋ก์‹œ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ๋„ ๋ณด์žฅํ•จ!
Member reference1 = em.getReference(Member.class, member.getId());
Member reference2 = em.getReference(Member.class, member.getId());
โ€‹
System.out.println("reference1 == reference2 : " + (reference1 == reference2)); // true

 

  • getReference()๋กœ ๋จผ์ € ๊ฐ€์ ธ์˜ค๊ณ , find()๋กœ ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋ฉด?
    • ๋‘˜๋‹ค ๊ฐ™์€ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ์กฐํšŒํ•˜๋Š” ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ์˜ ๋™์ผ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ)
Member reference = em.getReference(Member.class, member.getId());
Member find = em.find(Member.class, member.getId());
โ€‹
System.out.println("reference == find : " + (reference == find)); // true

 

์‹ค๋ฌด์—์„œ ๋งŽ์ด ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ์ค€์˜์† ์ƒํƒœ์ผ๋•Œ, ์ดˆ๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ํŠธ๋žœ์žญ์…˜์˜ ๋ฒ”์œ„ ๋ฐ–์—์„œ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋ ค๊ณ  ํ• ๋•Œ!

Member member = new Member();
member.setUsername("creator");
โ€‹
em.persist(member);
โ€‹
em.flush();
em.clear();
โ€‹
Member reference = em.getReference(Member.class, member.getId());
โ€‹
em.detach(reference);
//em.close, em.clear ๋ชจ๋‘
โ€‹
System.out.println("findMember.username = " + reference.getUsername());
โ€‹
tx.commit();
  • ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๋Š” org.hibernate.LazyInitializationException ์˜ˆ์™ธ๋ฅผ ํ„ฐํŠธ๋ฆฐ๋‹ค.

 

org.hibernate.LazyInitializationException: could not initialize proxy [hello.jpa.Member#1] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
at hello.jpa.Member$HibernateProxy$bCLaGKb1.getUsername(Unknown Source)
at JpaMain.main(JpaMain.java:35)

 

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ Spring boot์—์„œ open-in-view์„ค์ •์„ true๋กœ ๊ฐ€์ ธ๊ฐ.


 

์ฐธ์กฐ 

https://kingbbode.tistory.com/27

 

Spring - Open Session In View

Spring์—์„œ ORM์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉฐ, Transaction์„ ์ดํ•ดํ•  ๋•Œ ์ฏ”์Œ ๋‹ฅ์ณ์˜จ ํ˜ผ๋ž€์ด ์žˆ์Šต๋‹ˆ๋‹ค.์ง€์ธ์—๊ฒŒ ์ž์‹ ์žˆ๊ฒŒ Transaction์„ ์„ค๋ช…ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด Spring Boot๋กœ ๋น ๋ฅด๊ฒŒ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜ฌ๋ ธ๊ณ @GetMapping("/me

kingbbode.tistory.com

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

 

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

JPA๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜, ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์ด๋ก ์ด ๋ถ€์กฑํ•˜์‹  ๋ถ„๋“ค์ด JPA์˜ ๊ธฐ๋ณธ ์ด๋ก ์„ ํƒ„ํƒ„ํ•˜๊ฒŒ ํ•™์Šตํ•ด์„œ ์ดˆ๋ณด์ž๋„ ์‹ค๋ฌด์—์„œ ์ž์‹ ์žˆ๊ฒŒ JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., - ๊ฐ•์˜ ์†Œ๊ฐœ | ์ธํ”„๋Ÿฐ

www.inflearn.com

 

728x90