πŸ“š TIL 39일차

temprmnΒ·2023λ…„ 7μ›” 26일
0
post-thumbnail

μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ(1μ°¨ μΊμ‹œ)λ₯Ό ν™œμš©ν•œ 쓰기지연

데이터λ₯Ό μƒμ„±ν•œ ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜μ–΄λ„ 사라지지 μ•ŠλŠ” λ°μ΄ν„°μ˜ νŠΉμ„±μ„ λ§ν•œλ‹€. μ˜μ†μ„±μ„ 갖지 μ•ŠμœΌλ©΄ λ°μ΄ν„°λŠ” λ©”λͺ¨λ¦¬μ—μ„œλ§Œ μ‘΄μž¬ν•˜κ²Œ 되고, ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λ©΄ ν•΄λ‹Ή λ°μ΄ν„°λŠ” λͺ¨λ‘ μ‚¬λΌμ§€κ²Œ λœλ‹€. κ·Έλž˜μ„œ μš°λ¦¬λŠ” 데이터λ₯Ό νŒŒμΌμ΄λ‚˜ DB에 영ꡬ적으둜 μ €μž₯ν•¨μœΌλ‘œμ¨ μ˜μ†μ„±μ„ λΆ€μ—¬ν•œλ‹€.

μ˜μ†μ„± 4가지 μƒνƒœ

λΉ„μ˜μ† β–Ά μ˜μ† β–Ά μ€€μ˜μ† | μ‚­μ œ

  1. λΉ„μ˜μ†(new/transient): μ—”ν‹°ν‹° 객체가 λ§Œλ“€μ–΄μ Έμ„œ 아직 μ €μž₯λ˜μ§€ μ•Šμ€ μƒνƒœ. μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ μ „ν˜€ 관계가 μ—†μŒ.

  2. μ˜μ†(managed): μ—”ν‹°ν‹°κ°€ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯λ˜μ–΄, μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ 관리할 수 μžˆλŠ” μƒνƒœ.

  3. μ€€μ˜μ†(detached): μ—”ν‹°ν‹°κ°€ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯λ˜μ–΄ μžˆλ‹€κ°€ λΆ„λ¦¬λœ μƒνƒœ. μ˜μ†μ„± μ»¨ν…μŠ€νŠΈκ°€ 더 이상 κ΄€λ¦¬ν•˜μ§€ μ•ŠμŒ.

  4. μ‚­μ œ(removed): μ—”ν‹°ν‹°λ₯Ό μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ DBμ—μ„œ μ‚­μ œν•˜κ² λ‹€κ³  ν‘œμ‹œν•œ μƒνƒœ

객체의 μ˜μ†μ„± μƒνƒœλŠ” Entity Manager의 λ©”μ„œλ“œλ₯Ό 톡해 μ „ν™˜λœλ‹€. Raw JPA κ΄€μ μ—μ„œ μˆœμ„œλŒ€λ‘œ μš”μ•½ 정리λ₯Ό ν•΄λ³΄μžλ©΄...

  • Persist(), merge() β†’ (μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯된 μƒνƒœ: Managed) β†’ flush() β†’ (DB에 쿼리가 μ „μ†‘λœ μƒνƒœ) β†’ commit() β†’ (DB에 쿼리가 반영된 μƒνƒœ)

// 1️⃣ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— 담을 μƒν’ˆ μ—”ν‹°ν‹° 생성
Item item = new Item();
item.setItemNm("ν…ŒμŠ€νŠΈ μƒν’ˆ");	

// 2️⃣ μ—”ν‹°ν‹° λ§€λ‹ˆμ € νŒ©ν† λ¦¬λ‘œλΆ€ν„° μ—”ν‹°ν‹° λ§€λ‹ˆμ €λ₯Ό 생성
EntityManager em = entityManagerFactory.createEntityManager();
// 3️⃣ 데이터 λ³€κ²½ μ‹œ 무결성을 μœ„ν•΄ νŠΈλžœμž­μ…˜ μ‹œμž‘
EntityTransaction transaction = em.getTransaction();
transaction.begin();

// 4️⃣ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ— μ €μž₯된 μƒνƒœ, 아직 DB에 INSERT SQL 보내기 μ „
em.persist(item);
// 4️⃣-2 (DB에 SQL 보내기/commitμ‹œ μžλ™μˆ˜ν–‰λ˜μ–΄ μƒλž΅ κ°€λŠ₯함)
em.flush(item);
// 5️⃣ νŠΈλžœμž­μ…˜μ„ DB에 반영, 이 λ•Œ μ‹€μ œλ‘œ INSERT SQL 컀밋 μˆ˜ν–‰
transaction.commit();

// 6️⃣ μ—”ν‹°ν‹° λ§€λ‹ˆμ €μ™€ μ—”ν‹°ν‹° λ§€λ‹ˆμ € νŒ©ν† λ¦¬ μžμ›μ„ close() 호좜둜 λ°˜ν™˜
em.close();

μ“°κΈ° 지연이 λ°œμƒν•˜λŠ” μ‹œμ 

  • flush() λ™μž‘μ΄ λ°œμƒν•˜κΈ° μ „κΉŒμ§€ μ΅œμ ν™”.
  • flush() λ™μž‘μœΌλ‘œ μ „μ†‘λœ μΏΌλ¦¬λŠ” 더 이상 쿼리 μ΅œμ ν™”λŠ” λ˜μ§€ μ•Šκ³ , 이후 commit()으둜 반영만 κ°€λŠ₯.

μ“°κΈ° 지연 효과

  1. μ—¬λŸ¬ 개의 객체λ₯Ό 생성할 경우, λͺ¨μ•„μ„œ ν•œ λ²ˆμ— 쿼리λ₯Ό 전솑.

  2. μ˜μ†μ„± μ‚­νƒœμ˜ 객체가 생성 및 μˆ˜μ •μ΄ μ—¬λŸ¬ 번 μΌμ–΄λ‚˜λ”λΌλ„, ν•΄λ‹Ή νŠΈλžœμž­μ…˜ μ’…λ£Œ μ‹œ, μΏΌλ¦¬λŠ” 1번만 전솑될 수 있음.

  3. μ˜μ†μ„± μƒνƒœμ—μ„œ, 객체가 생성 ν›„ μ‚­μ œλ˜μ—ˆλ‹€λ©΄, μ‹€μ œ DBμ—λŠ” 아무 λ™μž‘μ΄ μ „μ†‘λ˜μ§€ μ•Šμ„ 수 있음.

  4. 즉, μ—¬λŸ¬κ°€μ§€ λ™μž‘μ΄ 많이 λ°œμƒν•˜λ”λΌλ„, μΏΌλ¦¬λŠ” νŠΈλžœμž­μ…˜ λ‹Ή μ΅œμ ν™” λ˜μ–΄ μ΅œμ†Œ 쿼리만 λ‚ μ•„κ°€κ²Œ 됨.

ν‚€ 생성 μ „λž΅μ΄ generationType.IDENTITY 둜 μ„€μ • λ˜μ–΄μžˆλŠ” 경우, 생성 μΏΌλ¦¬λŠ” 쓰기지연이 λ°œμƒν•˜μ§€ λͺ»ν•œλ‹€.

  • why? 단일 쿼리둜 μˆ˜ν–‰ν•¨μœΌλ‘œμ¨, μ™ΈλΆ€ νŠΈλžœμž­μ…˜μ— μ˜ν•œ 쀑볡 ν‚€ 생성을 λ°©μ§€ν•˜μ—¬ 단일킀λ₯Ό 보μž₯ν•˜κΈ° λ•Œλ¬Έμ—...

μ“°κΈ° 지연 예제 μ½”λ“œ

Team teamA = new Team();
teamA.setName("TeamA");
em.persist(teamA); // teamA: μ˜μ†μ„± μƒνƒœ

Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB); // teamB: μ˜μ†μ„± μƒνƒœ

Member member_A = new Member();
member_A.setName("memberA");
member_A.setTeam(teamA);

em.persist(member_A); // member_A: μ˜μ†μ„± μƒνƒœ

em.flush(); // * ← Insert 쿼리가 날아감

Member findMember = em.find(Member.class, member_A.getId());
Team findTeam = findMember.getTeam();

System.out.println(findTeam.getName());

1. flush()κ°€ μžˆλŠ” 경우

create member
create team
insert team      // flush둜 인해 쓰기지연이 λ°œμƒν•˜μ§€ μ•ŠμŒ
insert member    // flush둜 인해 쓰기지연이 λ°œμƒν•˜μ§€ μ•ŠμŒ
print "TeamA" (memberA.getTeam())

2. flush()κ°€ μ—†λŠ” 경우

create member
create team
print "TeamA" (memberA.getTeam()) // μ“°κΈ° 지연이 λ°œμƒν•˜λ”λΌλ„ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ—μ„œ μ‘°νšŒν•΄μ˜΄
insert team      // μ“°κΈ° 지연이 λ°œμƒν•œ λΆ€λΆ„
insert member    // μ“°κΈ° 지연이 λ°œμƒν•œ λΆ€λΆ„

Raw JPA 맀핑 κΈ°λŠ₯

@OneToMany (μΌλŒ€λ‹€ 관계)

  • κΈ°λ³ΈΒ FetchType ==Β LAZY.
  • 속성
    • mappedBy : μ—°κ΄€κ΄€κ³„μ˜ 주인 ν•„λ“œ
    • fetch : κΈ€λ‘œλ²Œ fetch μ „λž΅ μ„€μ •.
    • cascade : μ˜μ†μ„± 전이 κΈ°λŠ₯을 μ‚¬μš©.
    • targetEntity : μ—°κ΄€λœ μ—”ν‹°ν‹°μ˜ νƒ€μž… 정보λ₯Ό μ„€μ •.

@ManyToOne (λ‹€λŒ€μΌ 관계)

  • 속성
    • optional (default true) : false둜 μ„€μ •ν•˜λ©΄ μ—°κ΄€λœ μ—”ν‹°ν‹°κ°€ λ°˜λ“œμ‹œ μžˆμ–΄μ•Ό 함.
    • fetch : κΈ€λ‘œλ²Œ fetch μ „λž΅ μ„€μ •.
      • βœ‹Β κΈ°λ³Έμ΄ EGEAR 둜 μ„€μ •λ˜μ–΄μžˆμœΌλ‚˜ μ‹€λ¬΄μ—μ„œλŠ” κΈ°λ³Έ LAZY둜 μ„€μ •ν•˜λŠ”κ²ƒ μΆ”μ²œ!
    • cascade : μ˜μ†μ„± 전이 κΈ°λŠ₯ μ‚¬μš©.
    • targetEntity : μ—°κ΄€λœ μ—”ν‹°ν‹°μ˜ νƒ€μž… 정보 μ„€μ •.
      (targetEntity = Member.class μ‹μœΌλ‘œ μ‚¬μš©)

1. μΌλŒ€λ‹€ 단방ν–₯ 관계

@Entity(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToMany
	@JoinColumn(name = "parent_id")
    private List<Child> childList;
}

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

	@Column(name = "parent_id")
	private Long parentId;
}

2. λ‹€λŒ€μΌ μ–‘λ°©ν–₯ 관계

μΌλŒ€λ‹€ μ–‘λ°©ν–₯ κ΄€κ³„λŠ” μ—†μŒ!

@Entity(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToMany(mappedBy="parent")
    private List<Child> childList;
}

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

		@ManyToOne
		@JoinColumn(name = "parent_id")
		private Parent parent;
}
profile
`ISFJ` T 49% F 51% /

0개의 λŒ“κΈ€