π κ°μ
νλ‘μ νΈμμ νΈλμμ μ 물리μ μΌλ‘ λΆλ¦¬ν΄μΌ νκ³ , μ΄ κ³Όμ μμ λ΄λΆνΈμΆμ΄λΌλ κ°λ μ μκ² λμλ€. νΈλμμ λ΄λΆ νΈμΆμ΄λ 무μμ΄κ³ μ λ°μνλ κ²μ΄λ©° μ΄λ»κ² ν΄κ²°ν μ μλμ§ μμ보μ.
νΈλμμ μ΄λ?
νΈλμμ μ΄λ λ μ΄μ μͺΌκ°€ μ μλ μμ μ λ¨μμ΄λ€. μ¬κΈ°μ μμ μ λ°μ΄ν°λ² μ΄μ€μ μνλ₯Ό λ³κ²½νλ κ²μ μλ―Ένλ€. νΈλμμ μ νΉμ§μ λ€μκ³Ό κ°λ€.
- μμμ±(Atomicity): νΈλμμ λ΄μ μμ μ λͺ¨λ μ±κ³΅(Commit)νκ±°λ λͺ¨λ μ€ν¨(Rollback)λμ΄μΌ νλ€.
- μΌκ΄μ±(Consistency): νΈλμμ μ λ°μ΄ν°λ² μ΄μ€μ μνλ₯Ό μΌκ΄μ± μκ² μ μ§ν΄μΌ νλ€. ex) μ μ½ μ‘°κ±΄
- 격리μ±(Isolation): μ¬λ¬ νΈλμμ μ μλ‘ μν₯μ λ―ΈμΉμ§ μκ³ λ 립μ μΌλ‘ μνλμ΄μΌ νλ€.
- μ§μμ±(Durability): νΈλμμ μ΄ μ±κ³΅λμλ€λ©΄ λ°μ΄ν°λ² μ΄μ€μ μꡬμ μΌλ‘ λ°μλμ΄μΌ νλ€.
@Transactional
μ€νλ§μμλ AOPλ₯Ό μ¬μ©νμ¬ νΈλμμ μ μ μ©ν μ μλ€. @Transactional μ λ Έν μ΄μ μ ν΄λμ€λ λ©μλμ μ¬μ©νλ©΄ μ€νλ§μ ν΄λΉ ν΄λμ€λ‘λΆν° νλ‘μ κ°μ²΄λ₯Ό λ§λ€μ΄ 컨ν μ΄λμ λ±λ‘νλ€. μ€νλ§μμμ νΈλμμ λμ λ°©μμ λ€μκ³Ό κ°λ€.
- ν΄λΌμ΄μΈνΈκ° νλ‘μ κ°μ²΄μ λ©μλλ₯Ό νΈμΆ
- νλ‘μλ ν΄λΉ λ©μλκ° νΈλμμ μ μ¬μ©ν μ μλμ§ νμΈ
- νΈλμμ μμ
- μ€μ κ°μ²΄μ λ©μλ νΈμΆ
- νλ‘μλ‘ μ μ΄κ° λμμ€λ©΄ νλ‘μλ νΈλμμ μ Commit νκ±°λ Rollback
νλ‘μ λ΄λΆ νΈμΆ
μ μ€λͺ μ²λΌ @Transactionalμ μ μ©νλ €λ©΄ νμ νλ‘μ κ°μ²΄λ₯Ό ν΅ν΄μ λμ κ°μ²΄λ₯Ό νΈμΆν΄μΌ νλ€. νλ‘μ κ°μ²΄μμ λ¨Όμ νΈλμμ μ μ μ©ν μ΄νμ λμ κ°μ²΄λ₯Ό νΈμΆν΄μΌ νκΈ° λλ¬Έμ΄λ€. μ΄λ νλ‘μλ₯Ό κ±°μΉμ§ μκ³ λμ κ°μ²΄λ₯Ό μ§μ νΈμΆνκ² λλ©΄ AOPκ° μ μ©λμ§ μμ @Transactionalμ΄ μ μ©λμ§ μλλ€. μ΄λ¬ν μν©μ λ΄λΆνΈμΆμ΄λΌκ³ νλ€. μ½λλ‘ μ§μ νμΈν΄ 보μ.
νΈλμμ λ‘κ·Έ λ 벨μ λλ²κ·Έλ‘ μ€μ νλ©΄ νΈλμμ μ μμκ³Ό λμ λ‘κ·Έλ‘ νμΈν μ μλ€.
logging.level:
org.springframework.orm: debug
νλ‘μ κ°μ²΄ νΈμΆ
// TransactionService
@Transactional
public void outerTransaction() {
log.info("TransactionService.outerTransaction");
}
// Test
@Test
void callOuterTransaction() {
transactionService.outerTransaction();
}
νλ‘μ κ°μ²΄λ₯Ό ν΅ν΄μ νΈλμμ μ΄ μ μ©λ λ©μλλ₯Ό νΈμΆνλ―λ‘ μ μμ μΌλ‘ νΈλμμ μ΄ μ μ©λλ κ²μ νμΈν μ μλ€.
νλ‘μ λ΄λΆ νΈμΆ
μΈλΆ λ©μλμμ νΈμΆν λ΄λΆ λ©μλμ νΈλμμ μ μ ν μμ± REQUIERES_NEWλ₯Ό μ¬μ©ν΄ 보μ. μ΄λ‘ λλ‘λΌλ©΄ μΈλΆ λ©μλ νΈμΆ μ νΈλμμ μ΄ μμλκ³ λ΄λΆ λ©μλ νΈμΆ μ λ 립μ μΈ μλ‘μ΄ νΈλμμ μ΄ μμλμ΄μΌ νλ€.
// TransactionService
@Transactional
public void outerTransactionWithInnerTransaction() {
log.info("TransactionService.outerTransactionWithInnerTransaction");
innerTransaction();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerTransaction() {
log.info("TransactionService.innerTransactional");
}
// Test
@Test
void callOuterTransactionWithInnerTransaction() {
transactionService.outerTransactionWithInnerTransaction();
}
λ‘κ·Έλ₯Ό νμΈν΄ 보면 μΈλΆ λ©μλμ λν΄μλ§ νΈλμμ μ΄ μ μ©λμλ€. λ΄λΆ νΈλμμ μ΄ μΈλΆλ‘λΆν° λΆλ¦¬λμ§ μμκ³ μΌλ° λ©μλλ₯Ό νΈμΆν κ±°μ λμΌνκ² λμνλ€. κ·Έ μ΄μ λ 무μμΌκΉ?
λ΄λΆ νΈμΆ μ @Transactional μ λ Έν μ΄μ μ΄ μ μ©λμ§ μλ μ΄μ
μλ°μμλ λ©μλ μμ λ³λμ μ°Έμ‘°κ° μμ κ²½μ° thisλΌλ λ»μΌλ‘ μκΈ° μμ μ μΈμ€ν΄μ€λ₯Ό κ°λ¦¬ν€κ² λλ€. thisλ μκΈ° μμ μ κ°λ¦¬ν€λ μ€μ λμ κ°μ²΄μ μΈμ€ν΄μ€λ₯Ό μλ―Ένλ―λ‘ κ²°κ³Όμ μΌλ‘ νλ‘μλ₯Ό κ±°μΉμ§ μμ @Transactionalμ΄ μ μ©λμ§ μλλ€. λ°λΌμ μΌλ° λ©μλλ₯Ό νΈμΆνλ κ²κ³Ό λμΌνκ² λμνκ² λλ κ²μ΄λ€.
ν΄κ²° λ°©λ²
μ λ΄μ©μ μ΄ν΄νλ€λ©΄ ν΄κ²° λ°©λ²μ΄ μ½κ² λ μ€λ₯Ό κ²μ΄λ€. μΈλΆ λ©μλμμ μ€μ λμ κ°μ²΄κ° μλ νλ‘μ κ°μ²΄λ₯Ό ν΅ν΄ λ΄λΆ λ©μλλ₯Ό νΈμΆνλλ‘ μμ νλ©΄ λλ€. InnerTransactionService λ₯Ό μμ±νμ¬ μΈλΆ λ©μλμμ νλ‘μλ₯Ό ν΅ν΄ λ©μλλ₯Ό νΈμΆνλλ‘ μμ ν΄ λ³΄μ.
// InnerTransactionService
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerTransaction() {
log.info("InnerTransactionService.innerTransaction");
}
// TransactionService
@Transactional
public void outerTransactionWithInnerTransaction() {
log.info("TransactionService.outerTransactionWithInnerTransaction");
innerTransactionService.innerTransaction();
}
λ‘κ·Έλ₯Ό νμΈν΄ 보면 λ΄λΆ νΈλμμ μ΄ μΈλΆλ‘λΆν° λΆλ¦¬λμ΄ μλ‘μ΄ νΈλμμ μ μμ±νμ¬ λμνλ κ²μ νμΈν μ μλ€.
π κ²°λ‘
μ§κΈκΉμ§ νΈλμμ μ΄ νμνλ©΄ λ³μκ° μμ΄ @Transactional μ λ Έν μ΄μ μ λΆμ¬ μ¬μ©νλλ°, μ΄λ² κΈ°νλ‘ μ€νλ§μμ Transactional μ λ Έν μ΄μ μ΄ μ΄λ€ μμΌλ‘ λμνκ³ μ£Όμν΄μΌ ν μ μ΄ λ¬΄μμΈμ§ νμ΅ν μ μμλ€. μμΌλ‘ νΈλμμ μ΄ μλν λλ‘ λμνμ§ μκ±°λ μ μ©λκ³ μμ§ μλ€λ©΄ λ΄λΆνΈμΆμ νκ³ μλ κ² μλ μ§ νμΈν΄ λ΄μΌκ² λ€.