@Transactional
λ€μ΄κ°λ©΄μ
μ€νλ§μμ νΈλμμ μ
@Transactional
μ μ μΈνλ©΄ μ μ©ν΄λΉ κΈ°λ₯μ AOPλ₯Ό ν΅ν΄ ꡬν.
AOPκ° μ μ©λμλ μ§ νμΈνκΈ° μν΄μλ
.getClass()
λ₯Ό ν΅ν΄ν΄λμ€ μ΄λ¦μ νμΈν΄λ λ¨. ($$SpringCGLIB...
)νΉμ
AopUtils
λΌλ ν΄λμ€μμ μ 곡νλ λ©μλλ₯Ό ν΅ν΄ νμΈν΄λ³Ό μ λ μμ.그리κ³
public
λ©μλμλ§ μ μ©μ΄ κ°λ₯. (private
,protected
,package-visible
μ μ μ©μ΄ μλ¨.)protected
,package-visible
μ κ²½μ° μΈλΆμμ νΈμΆμ κ°λ₯νλ, μ€νλ§ μ체μμ μ μ©λμ§ μλλ‘ λ§κ³ μμ.
μ€νλ§μμ νΈλμμ μ λν κ΄λ¦¬λ
TransactionSynchronizationManager
μμ κ΄λ¦¬.ThreadLocal
μ΄λΌ, κ° μ€λ λ λ³λ‘ κ΄λ¦¬λλ€κ³ 보μ¬μ§.
@Transactional μ΅μ
μμμ μ°μ μμ?
μ€νλ§μμ μ°μ μμ?
νμ λ ꡬ체μ μΌλ‘ μμΈν κ²μ΄ λ λμ μ°μ μμλ₯Ό κ°μ§.
ν΄λμ€ vs λ©μλ -> λ©μλ
μΈν°νμ΄μ€ vs ν΄λμ€(μΈν°νμ΄μ€λ₯Ό ꡬνν) -> ν΄λμ€ (λ μμΈν κ²μ΄λ―λ‘)
@Transactional(readOnly = true)
static class LevelService {
@Transactional(readOnly = false)
public void write() {
log.info("call write");
}
}
μ΄μ κ°μ΄ μ μΈλμ΄μμ λ, νλ‘μκ° μ μ©λ LevelSerivce#writeλ₯Ό νΈμΆ νλ©΄, readOnly μ΅μ μ΄ falseλ‘ μ μ©λμ΄μ μ€νλ¨.
μ? λ ꡬ체μ μΈ κ²(λ©μλ) μ μ μ©λ μ΅μ μ΄ λ¨Όμ μ μ©λκΈ° λλ¬Έμ
@Transactional with Interface
μΈν°νμ΄μ€μ νΈλμμ μ μ μ©νλ λ°©λ²μ μ€νλ§μμ κΆμ₯νμ§ μλ λ°©λ².
μ?
AOPλ₯Ό μ μ©νλ λ°©μμ λ°λΌ, μΈν°νμ΄μ€μ μ¬μ©νμ κ²½μ° AOPκ° μλν λλ‘ λμνμ§ μμ μ μμ.
μ¦ μΈν°νμ΄μ€ κΈ°λ° νλ‘μλ₯Ό μ¬μ©νλ κ²½μ°μλ§, μ μ©ν μ μλ λ°©λ²
μΈν°νμ΄μ€ κΈ°λ° νλ‘μ vs ν΄λμ€ κΈ°λ° νλ‘μ
JDK Dynamic proxy vs CGLIB
μλ§λ Spring κΈ°λ³Έ AOP μ μ© κΈ°μ μ΄ CGLIB μ¦ ν΄λμ€ κΈ°λ°μ΄λ―λ‘, λ¬Έμ κ° λ°μν μ μμ΄μ μ΄λ κ² κΆμ₯νλ λ―
@Transactional μ¬μ©νλ©΄μ, λ°μν μ μλ λ¬Έμ μ
λ΄λΆ νΈμΆ
@Service
class CallService {
public void external() {
log.info("call external");
internal();
}
@Transactional
public void internal() {
log.info("call internal");
printTxInfo();
}
private void printTxInfo() {
boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
log.info("tx active={}", txActive);
}
}
Controllerμμ CallService#external (νλ‘μ μ μ©λ κ°μ²΄λ₯Ό κ±°μ³μ) λ₯Ό νΈμΆ νλ€κ³ κ°μ .
κ·Έλ¬λ©΄ external μμ, internal() μ΄ νΈμΆ λ κ².
μ΄λ΄ λ
@Transactional
μ΄ μ μ© λ κΉ? (txActive = true?)μλλ€.
μ?
Proxy κ°μ²΄λ₯Ό κ±°μ³μ νΈμΆλλ κ²μ΄ μλκΈ° λλ¬Έμ,
@Transactional
μ΄ λΆμ΄μμ΄λ μλ¬΄λ° κΈ°λ₯μ νμ§ λͺ»ν¨.μ¦ AOPκ° μ μ©λμ§ μμ.
μ 리νμλ©΄ Springμμ AOPκ° λμνλ λ°©μ λλ¬Έμ λ°μν μ μλ λ¬Έμ μ.
ν΄κ²°μ
internal()
λ‘ νΈμΆλλ λΆλΆμ λ€λ₯Έ ν΄λμ€λ‘ λΆλ¦¬νμ¬ AOPκ° μ μ©λ μνλ‘ νΈμΆλλλ‘ μμ νλ©΄ λ¨.
@PostContruct μ @Transactionalμ κ°μ΄ μ¬μ©ν κ²½μ°, νΈλμμ
μ΄ μ μ©λμ§ μλ λ¬Έμ
μ€νλ§ λΉ λΌμ΄ν μ¬μ΄ν΄
μ€νλ§ μ»¨ν μ΄λ μμ±
μ€νλ§ λΉ μμ±
μμ‘΄κ΄κ³μ£Όμ
μ΄κΈ°ν μ½λ°±μ¬μ© @PostConstruct
λΉ μ¬μ©
μλ©Έμ μ½λ°± @PreDestro
λΌμ΄ν μ¬μ΄ν΄λ‘ 미루μ΄λ³΄μ, 4λ²μμ
@PostContruct
μ€νν¨.4λ²μμ
@Transactional
μ λν νλ‘μ λΉμ΄ μ€νλ§ μ»¨ν μ΄λμ λͺ¨λ μ μ©λμλ€κ³ 보μ₯ν μ μμλ―@Transactional
μ λ¨Όμ μμκ° μλ¨μ μμ΄λ.. μλ λ―.
BeanPostProcessorλ 3~5λ² μ¬μ΄μ λμνλ―λ‘.
ν΄κ²°?
@EventListener(value = ApplicationReadyEvent.class)
@Transactional
public void init2() {
log.info("Hello init ApplicationReadyEvent");
}
@EventListener(value = ApplicationReadyEvent.class)
μ΄μ©νμ¬ μ ν리μΌμ΄μ μ΄ λͺ¨λ μ¬λΌμμ λ, νΈμΆλλλ‘.
@Transaciotnal μ΅μ
νΈλμμ
μμΈ, λ‘€λ°±
unchecked exception (Runtime exception, Error) λ°μ μ, λ‘€λ°±ν¨.
checked exeception (Exception) λ°μ μ, νΈλμμ 컀λ°.
λ‘κ·Έ μ΅μ μ ν΅ν΄, ν΄λΉ νΈλμμ μ§νμ λν λ‘κ·Έλ₯Ό λͺ¨λ νμΈν μ μμ.
logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
#JPA log
logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
logging.level.org.hibernate.resource.transaction=DEBUG
#JPA SQL
logging.level.org.hibernate.SQL=DEBUG
μ μΈμ²΄ν¬ μμΈλ λ‘€λ°±, μ²΄ν¬ μμΈλ 컀λ°?
μ²΄ν¬ μμΈλ λΉμ¦λμ€ μμΈκ° μμ.
λΉμ¦λμ€ μμΈ? μμ€ν μ μμΈλ μλμ§λ§, μμΈκ° λ°μ (μκ³ λΆμ‘± κ°μ)
κ·Έλμ λ‘€λ°±κΉμ§ νμ§ μμλ λ λ.
μλ₯Ό λ€μ΄, λ§μ½ λ‘€λ°±ν΄λ²λ¦¬λ©΄ κ³ κ°μ΄ μ£Όλ¬Έν μ£Όλ¬Έ μ 보κΉμ§ μμ΄μ§λ μΌμ΄ λ°μ. (λΆνμν..)
μΈμ²΄ν¬ μμΈλ 볡ꡬ λΆκ°λ₯νλ―λ‘, λμ μ μ¬μ©μκ° μκ²ν΄μΌν¨. μμ€ν μμΈ μλ₯Ό λ€λ©΄ λ€νΈμν¬ μ΄μ..
μ€μ²©λ νΈλμμ
μμμ 컀λ°κ³Ό λ‘€λ°±
νΈλμμ μ νλ κΈ°λ³Έ κ°μ (required)
νΈλμμ μ§ν μ€μ, κ·Έ νΈλμμ μ΄ μμ§ λλμ§ μμλ(컀λ°, λ‘€λ°±) λ° κ·Έ λ΄λΆμμ λλ€λ₯Έ νΈλμμ μ΄ μμ±λλ€λ©΄, μΈ, λ΄λΆ νΈλμμ λͺ¨λ νλμ νΈλμμ μΌλ‘ μ¬κ²¨μ§ (μ€νλ§ κΈ°λ³Έ λ°©μ)
νΈλμμ μ§ν μμ, λ λ€λ₯Έ νΈλμμ μ μμ±νλ€λ©΄..
νλμ 물리μ μΈ νΈλμμ μ΄ μ‘΄μ¬νλ©°, κ·Έ μμλ λ Όλ¦¬μ νΈλμμ μ΄ 2κ° μλ€κ³ λ³Ό μ μμ.
μ¦ λ¬Όλ¦¬ νΈλμμ = λ Όλ¦¬ νΈλμμ + λ Όλ¦¬ νΈλμμ
μ΄ νλμ νΈλμμ μΌλ‘ λ¬Άμ΄λ 건 물리μ μΌλ‘ μ¦ λ°μ΄ν°λ² μ΄μ€ λμμ μ΄μΌκΈ° νλ κ².
λ‘€λ°± μ λ΅?
λ Όλ¦¬ νΈλμμ μ€ νλλΌλ λ‘€λ°±λλ€λ©΄, 물리μ νΈλμμ μ λ‘€λ°±λ¨.
μ¦ λ Όλ¦¬ νΈλμμ λ€ λͺ¨λκ° λ¬Έμ μμ΄ μ»€λ° λμ΄μΌ, 물리μ νΈλμμ μ΄ μ»€λ°λλ€λ μ΄μΌκΈ° μ΄κ³ , 물리μ νΈλμμ μ΄ μ»€λ°λλ€λ 건 κ·ΈλμμΌ λ°μ΄ν°λ² μ΄μ€μ 컀λ°μ΄ λλ€λ μ΄μΌκΈ°
νΈλμμ μ€ν μμ, νμ¬ μνλ₯Ό νμΈ (TransactionSynchronizationManagerλ₯Ό ν΅ν΄) νμ¬ μ§νλκ³ μλ νΈλμμ μ΄ μλ μ§ νμΈ νλ€μμ, μμΌλ©΄ ν΄λΉ νΈλμμ μ μ΄μ©νλλ‘ ν¨.
ν΄λΉ νΈλμμ μ μ°Έμ¬νλ€? == μ무κ²λ μνλ€λ λ».
물리컀λ₯μ μ νλνκ±°λ.. μ΄λ° μΌλ ¨μ μμ μ νμ§ μνλ€λ λ».
νλμ 물리μ νΈλμμ μ΄ μκ³ , 2κ°μ λ Όλ¦¬μ νΈλμμ μ΄ μλ€κ³ κ°μ νμ.
μΈλΆ νΈλμμ (λ¨Όμ μμν νΈλμμ ) μ μ μμ μΌλ‘ 컀λ°λμλλ°, λ΄λΆ νΈλμμ (λμ€μ μμν)μ΄ λ‘€λ°±λλ€λ©΄?
κ²°κ³Όμ μΌλ‘ 물리μ νΈλμμ μ λ‘€λ°±λ κ²μ΄κ³ .
λ΄λΆ νΈλμμ μμ λ‘€λ°±λμμ λ, νΈλμμ μ μμ±κ°(rollback-only) λ³κ²½νμ¬, μΈλΆ νΈλμμ μ΄ μ»€λ° μ μ ν΄λΉ μμ±κ°μ 체ν¬νλλ° (컀λ°ν΄λ λ μ§), μ΄ κ°μ΄
true
μ΄κΈ° λλ¬Έμ, λ‘€λ°±λλ€.νΈλμμ λ§€λμ λ μ κ· νΈλμμ μΈμ§ μλμ§ μ¬λΆμ λ°λΌ, μ§μ§ 물리μ μΌλ‘ λ‘€λ°± ν μ§, μλλ©΄ μ μ νΈλμμ μ λ§ν¬λ§ ν μ§ κ²°μ ν¨.
μ 리νμλ©΄, λ΄λΆ νΈλμμ μ΄ λ‘€λ°±λλ©΄, 물리μ νΈλμμ μ λ‘€λ°±νμ§ μμ. κ·Έ λμ μ
rollback-only = true
μ λ§ν¬ν¨.κ·Έλμ μΈλΆ νΈλμμ μ΄ μ»€λ°νκΈ° μ μ, ν΄λΉ κ°μ λ³΄κ³ , λ‘€λ°±ν΄μΌ λ§μ§ νλ¨. λ§ν¬ λμ΄μλ€λ©΄ 물리μ νΈλμμ μ λ‘€λ°±νκ² λ¨.
그리κ³
UnexpectedRollbackException
μμΈλ₯Ό λμ§.
νΈλμμ
μ ν
REQUIRED
κΈ°λ³Έ
κ°μ₯ λ§μ΄ μ¬μ©ν¨.
κΈ°μ‘΄ νΈλμμ μμΌλ©΄, μ°Έμ¬ν¨.
κΈ°μ‘΄ νΈλμμ μμΌλ©΄ μμ±ν¨.
REQUIRED_NEW
νμ μλ‘μ΄ νΈλμμ μ μμ±νλ μ΅μ
κΈ°μ‘΄ νΈλμμ μμΌλ©΄, μλ‘ μμ±.
κΈ°μ‘΄ νΈλμμ μμΌλ©΄, μλ‘ μμ±.
μ¦ μΈλΆ, λ΄λΆλ₯Ό μμ ν λΆλ¦¬ν΄μ μ¬μ©νλ λ°©λ². μ¦ λ¬Όλ¦¬μ μΌλ‘ μμ ν λΆλ¦¬νλ λ°©λ²μ.
ν΄λΉ μ΅μ μ νΈλμμ μ΄ νΈμΆλλ μμ μ, 컀λ₯μ νμ 컀λ₯μ μ΄ λΆμ‘±νλ©΄.. λ°λλ½μ΄ 걸릴 κ°λ₯μ± μμ.
timeoutμ΄ μκΈ° λλ¬Έμ, μ΄λ μμ μμλ λ‘€λ°±λκ² μ§λ§..
μ? μ΄κ² μ λ‘€λ°±λλκ±°μ§? μΆκ°μ μΌλ‘ μ½μ΄λ΄μΌν κ².
SUPPORT
NOT_SUPPORT
MANDATORY
NEVER
NESTED
κΈ°μ‘΄ νΈλμμ μ΄ μμΌλ©΄, μλ‘μ΄ νΈλμμ μμ±.
κΈ°μ‘΄ νΈλμμ μ΄ μμΌλ©΄, μ€μ²© νΈλμμ μ μμ±
μ€μ²© νΈλμμ ?
μ΄ νΈλμμ μ μΈλΆ νΈλμμ μ μν₯μ λ°μ§λ§, μ΄ νΈλμμ μ΄ μΈλΆ νΈλμμ μ μν₯μ μ£Όμ§ μμ.
e.g μΈλΆ νΈλμμ λ‘€λ°± -> μ€μ²© νΈλμμ λ‘€λ°±, μ€μ²© νΈλμμ λ‘€λ°± -> μΈλΆ νΈλμμ μ»€λ° κ°λ₯
νΈλμμ
μ ν, μ΅μ
μ μ μ©
isolation
,timeout
,readOnly
λ±μ μ΅μ μ νΈλμμ μ΄ μλ‘ μμν λλ§ μ μ©λ¨.e.g
REQUIRED
μμ κΈ°μ‘΄ νΈλμμ μ΄ μκ³ , μλ‘μ΄ νΈλμμ μ μμν λ μ μ©, μ°Έμ¬ν λλ ν΄λΉ νΈλμμ μ μ΅μ μ΄ μμ΄λ μ μ©μ΄ μλλ€. (μΈλΆ νΈλμμ μ΅μ μ΄ μ μ©λ¨.)
μ°Έκ³
Last updated
Was this helpful?