처음 본 @Transactional

2024. 1. 28. 06:11ㆍBackend/Spring

μ „ 직μž₯μ—μ„œ NestJS - TypeOrm을 톡해 κ°œλ°œμ„ 진행해왔고, 퇴사 ν›„ Spring에 ν•œλ²ˆ μž…λ¬Έν•΄λ³΄μžλŠ” μƒκ°μœΌλ‘œ κ°„λ‹¨ν•œ ν”„λ‘œμ νŠΈλ₯Ό 진행 μ€‘μž…λ‹ˆλ‹€.

 

GitHub - One-armed-boy/spring_stream_video: λΉ„λ””μ˜€ 슀트리밍 μ„œλ²„ with Spring boot

λΉ„λ””μ˜€ 슀트리밍 μ„œλ²„ with Spring boot. Contribute to One-armed-boy/spring_stream_video development by creating an account on GitHub.

github.com

처음 κ΅¬μƒν–ˆλ˜ μ•„μ£Ό 기초적인 κΈ°λŠ₯만 κ΅¬ν˜„ν•œ λ’€ 주변에 계신 μŠ€ν”„λ§ 개발자 λΆ„κ»˜ κ°„λ‹¨νžˆ μ½”λ“œ 리뷰λ₯Ό λ°›μ•˜λŠ”λ°, @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ˜ ν™œμš©μ— λŒ€ν•΄ 받은 리뷰가 특히 기얡이 λ‚©λ‹ˆλ‹€.

이 λ•Œ μ•„λ¬΄λž˜λ„ κΈ°μ‘΄ TypeOrm 기반 νŠΈλžœμž­μ…˜ μ²˜λ¦¬μ— μ΅μˆ™ν•΄μ Έμžˆλ˜ 상황이고, Spring μ»¨ν…μŠ€νŠΈμ—μ„œ DB κ΄€λ ¨ 처리λ₯Ό μ–΄λ–»κ²Œ μˆ˜ν–‰ν•˜λŠ”μ§€ μ „ν˜€ λͺ¨λ₯΄λ˜ 상황이라 이에 λŒ€ν•΄ 개인적으둜 곡뢀해보기 μœ„ν•΄ ν•΄λ‹Ή 포슀트λ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.

 

@Transactionalμ΄λž€

μ΄λŠ” Spring λ“±μ—μ„œ κ°„λ‹¨νžˆ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ„€μ •ν•˜λŠ” 것 만으둜 νŽΈλ¦¬ν•˜κ²Œ νŠΈλžœμž­μ…˜μ„ λ‹€λ£° 수 있게 ν•΄μ£ΌλŠ” μ£Όμ²΄μž…λ‹ˆλ‹€. 

이λ₯Ό μ‚¬μš©ν•˜λ©΄ λ“±λ‘λœ λ©”μ„œλ“œκ°€ 호좜될 λ•Œ ν”„λ‘μ‹œλ₯Ό 톡해 μžλ™μ μœΌλ‘œ νŠΈλžœμž­μ…˜μ˜ 생λͺ…μ£ΌκΈ°λ₯Ό 생성해주어 κ°œλ°œμžλŠ” νŠΈλžœμž­μ…˜ 관리λ₯Ό 신경쓰지 μ•Šκ³  λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— 집쀑할 수 μžˆλ‹€λŠ” μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

μ•„λž˜μ²˜λŸΌ μ‚¬μš©λ©λ‹ˆλ‹€.

// μΈν„°νŽ˜μ΄μŠ€ λ ˆλ²¨μ— μ„€μ •
@Transactional
public interface TestService {
  // μΈν„°νŽ˜μ΄μŠ€ λ©”μ„œλ“œ λ ˆλ²¨μ— μ„€μ •
  @Transactional
  public void add();
}

// 클래슀 λ ˆλ²¨μ— μ„€μ •
@Transactional
public class TestServiceImpl {
  // 클래슀 λ©”μ„œλ“œ λ ˆλ²¨μ— μ„€μ •
  @Transactional
  public void add() {
    ...
  }
}

μœ„ μ˜ˆμ‹œμ²˜λŸΌ 총 넀가지 μ»¨ν…μŠ€νŠΈ(μΈν„°νŽ˜μ΄μŠ€, μΈν„°νŽ˜μ΄μŠ€ λ©”μ„œλ“œ, 클래슀, 클래슀 λ©”μ„œλ“œ)μ—μ„œ ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 λ•Œ 적용 μš°μ„ μˆœμœ„λŠ” 클래슀 λ©”μ„œλ“œ -> 클래슀 -> μΈν„°νŽ˜μ΄μŠ€ λ©”μ„œλ“œ -> μΈν„°νŽ˜μ΄μŠ€ 순이 λ©λ‹ˆλ‹€.

 

νŠΈλžœμž­μ…˜ μ „νŒŒ 속성

Java Spring ν™˜κ²½μ΄ μ΅μˆ™μΉ˜ μ•Šμ€ μ €μ—κ²ŒλŠ” μƒμ†Œν•œ κ°œλ…μ΄μ—ˆμŠ΅λ‹ˆλ‹€.

λ‹€λ§Œ μ–΄λ–€ κ°œλ…μΈμ§€ 감을 μž‘κ³ λ‚˜λ‹ˆ μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ„ λ†’μ—¬μ£ΌλŠ” 쒋은 κΈ°λŠ₯μ΄λΌλŠ” 생각이 λ“€μ—ˆμŠ΅λ‹ˆλ‹€.

νŠΈλžœμž­μ…˜ μ „νŒŒ μ†μ„±μ΄λž€, 이미 μƒμ„±λœ νŠΈλžœμž­μ…˜ λ‚΄λΆ€μ—μ„œ λ‹€μ‹œ @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ μ–΄λ–»κ²Œ μ²˜λ¦¬ν• μ§€μ— λŒ€ν•œ κ°œλ…μž…λ‹ˆλ‹€.

λ§Œμ•½ 이미 @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ™μ—¬λ‘” DML μ„œλΉ„μŠ€ 둜직 Aκ°€ μžˆλ‹€κ³  κ°€μ •ν•©μ‹œλ‹€. 이 λ•Œ λ‹€λ₯Έ μ„œλΉ„μŠ€μ—μ„œ ν•΄λ‹Ή μ„œλΉ„μŠ€μ˜ DML λ‘œμ§μ„ μ—¬λŸ¬λ²ˆ ν˜ΈμΆœν•˜κ³  ν•œλ²ˆμ΄λΌλ„ μ‹€νŒ¨ν–ˆμ„ 경우 λͺ¨λ“  DML을 λ‘€λ°±ν•˜κ³  싢은 상황이 λ°œμƒν–ˆμ„ λ•Œ, μƒμœ„ νŠΈλžœμž­μ…˜μ΄ A의 λ‘œμ§μ— μ „νŒŒλ˜μ§€ μ•ŠλŠ”λ‹€λ©΄ 두 νŠΈλžœμž­μ…˜μ€ 사싀상 λ…λ¦½λœ νŠΈλžœμž­μ…˜μœΌλ‘œ μ—¬κ²¨μ§ˆν…Œλ‹ˆ ν•œλ²ˆμ— λ‘€λ°±ν•  μˆ˜κ°€ 없어지고 이둜 인해 A의 λ‘œμ§μ„ λ³΅λΆ™ν•΄μ•Όν•˜λŠ” 상황이 λ°œμƒν•©λ‹ˆλ‹€.

νŠΈλžœμž­μ…˜ μ „νŒŒ 섀정을 톡해 μ΄λŸ¬ν•œ 문제λ₯Ό μš°μ•„ν•˜κ²Œ ν•΄κ²°ν•  수 μžˆμ–΄μ§€λŠ” κ²ƒμž…λ‹ˆλ‹€. 

μ „νŒŒ μ†μ„±μœΌλ‘œλŠ” λ‹€μ–‘ν•œ μ˜΅μ…˜μ„ 쀄 수 μžˆλŠ”λ°, λͺ‡κ°œλ§Œ 좔리면 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • REQUIRED: 이미 μƒμ„±λœ νŠΈλžœμž­μ…˜μ΄ μžˆλ‹€λ©΄ 그에 μ°Έμ—¬ν•˜κ³ , 그렇지 μ•Šλ‹€λ©΄ μƒˆλ‘œ νŠΈλžœμž­μ…˜ 생성
  • REQUIRES_NEW: 이미 μƒμ„±λœ νŠΈλžœμž­μ…˜μ˜ μœ λ¬΄μ— κ΄€λ ¨ 없이, 항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜ 생성
  • SUPPORTS: 이미 μƒμ„±λœ νŠΈλžœμž­μ…˜μ΄ μžˆλ‹€λ©΄ 그에 μ°Έμ—¬ν•˜κ³ , 그렇지 μ•Šλ‹€λ©΄ νŠΈλžœμž­μ…˜ 없이 μ‹€ν–‰

 λ” λ§Žμ€ μ˜΅μ…˜μ€ μ•„λž˜ λ§ν¬μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

https://www.baeldung.com/spring-transactional-propagation-isolation#transaction-propagations

 

λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— λͺ…μ‹œμ  @Transactional을 λΆ™μ—¬μ£ΌλŠ” 이유

μ„œλ‘ μ—μ„œ μ–ΈκΈ‰ν•œ μ½”λ“œ λ¦¬λ·°μ—μ„œ μ €λŠ”, μ™œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ„ 뢙여주지 μ•Šμ•˜λƒλŠ” μ§ˆλ¬Έμ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€. 

κ·Έ λ•Œ 제 λ…Όλ¦¬λŠ” μ•„λž˜μ™€ κ°™μ•˜μŠ΅λ‹ˆλ‹€.

  • 단일 μΏΌλ¦¬λŠ” μ–΄μ°¨ν”Ό DB μ„œλ²„ μΈ‘μ—μ„œ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ μž‘μš©ν•˜λŠ”λ°, ꡳ이 νŠΈλžœμž­μ…˜μ„ λͺ…μ‹œμ μœΌλ‘œ μ²˜λ¦¬ν•΄μ€„ ν•„μš”κ°€ μžˆλŠλƒ
  • μ„œλΉ„μŠ€ 둜직 전체에 μ μš©ν•˜λŠ” 것은 λΆˆν•„μš”ν•˜κ²Œ νŠΈλžœμž­μ…˜μ˜ 길이λ₯Ό 길게 λ§Œλ“œλŠ” 것 μ•„λ‹Œκ°€
  • μ—¬λŸ¬ 쿼리가 ν•˜λ‚˜μ˜ μ›μž λ‹¨μœ„λ‘œ μž‘μš©ν•΄μ•Όν•  λ•Œμ™€, μ„œλ²„ μΈ‘μ—μ„œ 좔가적인 검증을 톡해 λͺ…μ‹œμ μœΌλ‘œ λ‘€λ°±ν•΄μ•Όν•˜λŠ” 상황이 μ•„λ‹ˆλΌλ©΄ ꡳ이...?

이 글을 μž‘μ„±ν•˜κ³  μžˆλŠ” 이 μ‹œμ μ—” 생각이 λ°”λ€Œμ—ˆκΈ° λ•Œλ¬Έμ— μžλ¬Έμžλ‹΅ν•˜λŠ” μ‹μœΌλ‘œ μœ„μ˜ 논리λ₯Ό λ°˜λ°•ν•˜κ² μŠ΅λ‹ˆλ‹€.

단일 μΏΌλ¦¬λŠ” μ–΄μ°¨ν”Ό DB μ„œλ²„ μΈ‘μ—μ„œ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ μž‘μš©ν•˜λŠ”λ°, ꡳ이 νŠΈλžœμž­μ…˜μ„ λͺ…μ‹œμ μœΌλ‘œ μ²˜λ¦¬ν•΄μ€„ ν•„μš”κ°€ μžˆλŠλƒ

이 논리λ₯Ό 펼칠 λ‹Ήμ‹œ μ œκ°€ λͺ°λžλ˜ 사싀은, JpaRepository μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒμ†ν•œ Repositoryμ—μ„œ μ΄λ£¨μ–΄μ§€λŠ” 기본적인 DA μž‘μ—…μ€ λͺ…μ‹œμ μœΌλ‘œ μ „λΆ€ @Transactional이 λΆ™μ–΄μžˆλ‹€λŠ” μ μž…λ‹ˆλ‹€.

μ΄λŠ” JpaRepository의 μ‹€μ§ˆμ μΈ κ΅¬ν˜„μ²΄μΈ SimpleJpaRepository(springframework.data.jpa.repository.support.SimpleJpaRepository) 클래슀λ₯Ό 보면 μ•Œ 수 μžˆλŠ”λ°, 이에 κ΅¬ν˜„λœ DA용 λ©”μ„œλ“œ(ex. findAll, save λ“±)μ—λŠ” λͺ¨λ‘ @Transactional이 이미 λ‹¬λ €μžˆμŠ΅λ‹ˆλ‹€. 

SimpleJpaRepository 클래슀의 μ†ŒμŠ€μ½”λ“œ 일뢀

λ”°λΌμ„œ μ œκ°€ DB μ„œλ²„ μΈ‘μ—μ„œ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ μžλ™ 취급될 것이라고 μ΄μ•ΌκΈ°ν•œ λ‚΄μš©μ€ 이미, λ…Όμ˜μ˜ μ „μ œλΆ€ν„° 잘λͺ»λœ κ²ƒμž…λ‹ˆλ‹€. μ œκ°€ @Transactional을 걸든말든, μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 레벨의 λͺ…μ‹œμ μΈ νŠΈλžœμž­μ…˜μ€ μ‹œμž‘λ©λ‹ˆλ‹€.

μ„œλΉ„μŠ€ 둜직 전체에 μ μš©ν•˜λŠ” 것은 λΆˆν•„μš”ν•˜κ²Œ νŠΈλžœμž­μ…˜μ˜ 길이λ₯Ό 길게 λ§Œλ“œλŠ” 것 μ•„λ‹Œκ°€

항상 νŠΈλžœμž­μ…˜μ΄ μž‘μ€ 크기λ₯Ό μœ μ§€ν•˜λŠ” 것은 μ€‘μš”ν•©λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘ν•˜κ³  μ»€λ°‹λ˜κΈ°κΉŒμ§€ 였래 κ±Έλ¦¬λŠ” 상황이 μž¦λ‹€λ©΄ DB μΈ‘ μ„±λŠ₯에 μ•…μ˜ν–₯을 쀄 수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. (MVCCκ°€ μžˆλ‹€κ³  해도, 이λ₯Ό μœ„ν•΄ DB μ„œλ²„ μΈ‘μ—μ„œ μœ μ§€ν•΄μ•Όν•˜λŠ” λ¦¬μ†ŒμŠ€λ‘œ 인해 μ•…μ˜ν–₯을 생길 수 밖에 μ—†λ‹€.) 

이 문제둜 인해 쑰금 고민을 ν•΄λ΄€λŠ”λ°, 제 λ‚˜λ¦„λŒ€λ‘œ λ‚΄λ¦° 결둠은 일반적인 κ²½μš°μ—μ„  문제 μ—†λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 이 μƒν™©μ—μ„œ λ“±μž₯ν•˜λŠ” 일반적인 μ˜ˆμ‹œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  1. νŠΈλžœμž­μ…˜ Start
  2. μ‚¬μš©μž 데이터 검증
  3. DML μš”μ²­
  4. μ™ΈλΆ€ API μš”μ²­(ex. 이메일 λ°œμ†‘ λ“±)
  5. Commit

그리고 μœ„ λ‘œμ§λ“€μ€ κ°„λ‹¨νžˆ UserServiceμ—μ„œ μ–΄λ–€ ν•œ λ©”μ„œλ“œμ˜ μž‘λ™ 방식이라 κ°€μ •ν•©μ‹œλ‹€. 이 λ•Œ μ˜¬λ°”λ₯Έ νŠΈλžœμž­μ…˜ 경계 μ„€μ •μ˜ μ˜ˆμ‹œλŠ” μ•„λž˜μ²˜λŸΌ 기술되곀 ν•©λ‹ˆλ‹€.

  1. μ‚¬μš©μž 데이터 검증
  2. νŠΈλžœμž­μ…˜ Start
  3. DML μš”μ²­
  4. Commit
  5. μ™ΈλΆ€ API μš”μ²­(ex. 이메일 λ°œμ†‘ λ“±)

ν™•μ‹€νžˆ μˆ˜μ • 전보닀 더 λ‚˜μ•„λ³΄μž…λ‹ˆλ‹€. 그런데 이 경우, 선언적 νŠΈλžœμž­μ…˜μ„ 톡해선 UserServiceμ—μ„œ κ΅¬ν˜„ν•˜λŠ”κ²Œ μ–΄λ €μ›Œμ§‘λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ©΄ ν”„λ‘œκ·Έλž˜λ° 방식 νŠΈλžœμž­μ…˜μœΌλ‘œ ν‹€μ–΄μ•Όν• κΉŒμš”?

μ œκ°€ 이 μ½”λ“œλ₯Ό λ¦¬λ·°ν•˜λŠ” 상황이 μ˜¨λ‹€λ©΄, κ·Έλ³΄λ‹€λŠ” UserService의 μ±…μž„μ΄ κ³Όλ„ν•˜λ‹€κ³  ν•  것 κ°™μŠ΅λ‹ˆλ‹€. μ• μ΄ˆμ— UserServiceκ°€ λ§ˆλ•…νžˆ μ±…μž„μ Έμ•Όν•˜λŠ” 뢀뢄이 λ°”λ‘œ μˆ˜μ • ν›„ νŠΈλžœμž­μ…˜μœΌλ‘œ λž˜ν•‘λœ 둜직이 μ•„λ‹κΉŒ ν•˜κ΅¬μš”. 그리고 μœ„ 전체 λ‘œμ§μ€ LoginFacade 같은 객체λ₯Ό μƒμ„±ν•˜μ—¬ 거기에 μ±…μž„μ„ λΆ€μ—¬ν•˜λŠ” μ‹μœΌλ‘œ μž‘μ—…ν•  것 κ°™μŠ΅λ‹ˆλ‹€.

그리고 이λ₯Ό 쑰금 ν™•μž₯ν•΄μ„œ, μ™ λ§Œν•œ κ²½μš°μ—μ„  μ„œλΉ„μŠ€ λ ˆμ΄μ–΄μ— 선언적 νŠΈλžœμž­μ…˜μ„ κ±Έμ–΄μ€€λ‹€κ³  해도 μ„±λŠ₯ 상 λ¬Έμ œκ°€ μ—†μœΌλ¦¬λΌ κ²°λ‘  μ§€μ—ˆμŠ΅λ‹ˆλ‹€. 

그리고 이 결둠을 ν†΅ν•˜λ©΄ λ§ˆμ§€λ§‰ 3번째 논리도 λ°˜λ°•μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ—¬λŸ¬ 쿼리가 ν•˜λ‚˜μ˜ μ›μž λ‹¨μœ„λ‘œ μž‘μš©ν•΄μ•Όν•  λ•Œμ™€, μ„œλ²„ μΈ‘μ—μ„œ 좔가적인 검증을 톡해 λͺ…μ‹œμ μœΌλ‘œ λ‘€λ°±ν•΄μ•Όν•˜λŠ” 상황이 μ•„λ‹ˆλΌλ©΄ ꡳ이...?

κ·Έλž˜μ„œ λͺ…μ‹œμ μœΌλ‘œ λΆ™μ—¬μ•Ό ν•˜λŠ” μ΄μœ λŠ”?

μ±…μž„μ„ 잘 λΆ„λ¦¬ν•œ μ„œλΉ„μŠ€ λ ˆμ΄μ–΄λΌλ©΄, κ²°κ΅­ ν•΄λ‹Ή λ ˆμ΄μ–΄μ—μ„œ μˆ˜ν–‰ν•˜λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§λ“€μ€ DB의 μƒνƒœμ™€ 큰 관련이 μžˆμ„ κ°€λŠ₯성이 ν½λ‹ˆλ‹€. λ”°λΌμ„œ λͺ…μ‹œμ μœΌλ‘œ @Transactional(readonly = true) μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ™μ—¬μ£ΌλŠ” 것은 μ‹€μ œλ‘œ νŠΈλžœμž­μ…˜μ΄ ν•„μš”ν•œ κ²½μš°μ—μ„œ μ‹€μˆ˜ν•  κ°€λŠ₯성을 크게 쀄여쀄 κ²ƒμž…λ‹ˆλ‹€. (μœ„μ—μ„œ μ΄μ•ΌκΈ°ν–ˆλ“―μ΄ 뢙인닀고 크게 λ¬Έμ œκ°€ λ˜λŠ” 것도 μ•„λ‹ˆκ΅¬μš” γ…Žγ…Ž)

β€» 2024.02.04 μΆ”κ°€

@Transactional이 μ„œλΉ„μŠ€ λ ˆμ΄μ–΄μ— 없을 경우, μ˜μ†μ„± μ»¨ν…μŠ€νŠΈμ™€ μ—”ν‹°ν‹° setterλ₯Ό ν†΅ν•œ μžμ—°μŠ€λŸ¬μš΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ - DB 동기화가 λΆˆκ°€λŠ₯ν•˜κ³  λͺ…μ‹œμ μœΌλ‘œ μ˜μ†μ„± μ»¨ν…μŠ€νŠΈλ₯Ό 관리해주어야 ν•˜λŠ” λ¬Έμ œλ„ μžˆμŠ΅λ‹ˆλ‹€.

 

ν›„κΈ°

νŠΈλžœμž­μ…˜μ˜ μ œλ„€λŸ΄ν•œ κ°œλ…λ“€(고립 레벨 같은)은 μ˜λ„μ μœΌλ‘œ 닀루지 μ•Šμ•˜κ³  μ œκ°€ λͺ°λžλ˜ μžλ°” μͺ½ 이야기λ₯Ό μœ„μ£Όλ‘œ λ‹€λ€˜μŠ΅λ‹ˆλ‹€. 글을 μž‘μ„±ν•˜λ©΄μ„œ Spring의 DB Access 파트λ₯Ό 같이 κ³΅λΆ€ν•œ λŠλ‚ŒμΈλ°, 보면 볼수둝 잘 λͺ¨λ₯΄λŠ” 뢀뢄듀이 계속 νŠ€μ–΄λ‚˜μ™€μ„œ μ’€ λ‹Ήν™©... (특히 μ˜μ†μ„± μ»¨ν…μŠ€νŠΈ 같은)

 

μ°Έκ³  λ¬Έμ„œ

ν† λΉ„μ˜ μŠ€ν”„λ§ 3.1 - 이일민 μ €

 

Why do I need Transaction in Hibernate for read-only operations?

Why do I need Transaction in Hibernate for read-only operations? Does the following transaction put a lock in the DB? Example code to fetch from DB: Transaction tx = HibernateUtil.getCurrentS...

stackoverflow.com

 

 

@Transactional λ°”λ₯΄κ²Œ μ•Œκ³  μ‚¬μš©ν•˜κΈ°

@Transactional κ·Έκ±° μ–΄λ–»κ²Œ λ™μž‘ν•˜λŠ” κ±΄κ°€μš”?

medium.com

 

 

Spring Transaction Best Practices - Vlad Mihalcea

Learn various Spring Transaction Best Practices to help you provide data integrity without sacrificing performance.

vladmihalcea.com