μ¬λ¬κ°μ μμ λ€μ νλμ κ·Έλ£ΉμΌλ‘ λ¬Άμ΄μ μ²λ¦¬νλ μ²λ¦¬ λ¨μ
μ¬λ¬ κ°μ μμ
μ΄ νλμ μμ
μΌλ‘ μΈμν΄μ μ λΆ μ±κ³΅νλ κ° μ λΆ μ€ν¨νλ κ°(All or Nothing)μ λ μ€ νλλ‘λ§ μ²λ¦¬λμ΄μΌ νΈλμμ
μ μλ―Έλ₯Ό κ°μ§
β λ°μ΄ν°μ 무결μ±μ 보μ₯νλ ν΅μ¬μ μΈ μν
μ λ’°ν μ μλ μ ν리μΌμ΄μ
μ ꡬμΆνκΈ° μν΄μ κ°μ₯ μ€μν λΆλΆ μ€ νλ
( μ ν리μΌμ΄μ
μ μ λ’°μ±μ΄ κΉ¨μ§λ μν©μ΄ λ°μνλ©΄ νΈλμμ
μ΄λΌκ³ λΆλ₯Ό μ μμ )
λΆκ° κΈ°λ₯μ΄κΈ° λλ¬Έμ AOPμ μ μ© λμ μ€ νλ
λ‘컬 νΈλμμ / λΆμ° νΈλμμ μΌλ‘ λλ¨
βοΈ λ‘컬 νΈλμμ
νλμ μμ κ΄λ¦¬μ(λ°μ΄ν°λ² μ΄μ€)κ° μ°Έμ¬νλ νΈλμμ
β
βοΈ λΆμ° νΈλμμ
νλ μ΄μμ μμ κ΄λ¦¬μ(λ°μ΄ν°λ² μ΄μ€)μ νλ μ΄μμ 물리μ μΈ μ¬μ΄νΈκ° νλμ λ Όλ¦¬μ μΈ λ¨μλ‘ μ°Έμ¬νλ νΈλμμ
λ°μ΄ν°λ² μ΄μ€μ κ΄λ ¨μ΄ μλ νμλ μ¬λ¬ μμ
μ΄ μμμ±μ κ°μ§κ³ μ²λ¦¬λμ΄μΌ νλ€λ©΄ νλμ νΈλμμ
μΌλ‘ λ³Ό μ μμ
Ex. νμΌ μμ± λ° μ
λ‘λ, μ΄λ©μΌ μ μ‘, λ©μμ§ μ μ‘ λ±
π‘ νΈλμμ λ²μμ μμμ± μ»¨ν μ€νΈ, Fascade λ²μ
[μ°Έκ³ ] https://willseungh0.tistory.com/73
μ μΈν νΈλμμ λ°©μ
νλ‘κ·Έλλ° μ½λ λ² μ΄μ€ νΈλμμ
λ°©μ
( μ΄κ±΄ 그리 μ μ ν νΈλμμ
λ°©μμ΄ μλ )
β Spring Boot μμ νΈλμμ
μ μ¬μ©ν κ²½μ°, κ΄λ ¨ μ€μ μμ΄ λ΄λΆμ μΌλ‘ μμμ ν΄μ€
( Spring Bootμ μ¬μ©νμ§ μμ κ²½μ° λ°λ‘ μ€μ μ ν΄μ€μΌν¨ )
π‘ Spring μμμ νΈλμμ
- PlatformTransactionManagerμ μν΄ κ΄λ¦¬λ¨
PlatformTransactionManager μΈν°νμ΄μ€λ₯Ό ꡬνν΄μ ν΄λΉ λ°μ΄ν° μ‘μΈμ€ κΈ°μ μ λ§κ² μ μ°νκ² νΈλμμ μ μ μ© ν μ μλλ‘ μΆμν λμ΄ μμ
β μ°λ¦¬κ° μ¬μ©νλ JPA λ°μ΄ν° μ‘μΈμ€ κΈ°μ μ μ¬μ©νλ€λ©΄, PlatformTransactionManagerμ ꡬν ν΄λμ€μΈ JpaTransactionManager μ¬μ©
μμ μ λμ΄μ μͺΌκ°€ μ μμ
νλμ μμ μΌλ‘ μΈμν΄μ λ λ€ μ±κ³΅νλ κ° λ λ€ μ€ν¨νλ κ°(All or Nothing) μ€μμ νλλ‘λ§ μ²λ¦¬λλ κ²μ΄ 보μ₯λμ΄μΌ ν¨
νΈλμμ μ΄ μλ£λλ©΄ κ·Έ κ²°κ³Όλ μ§μλμ΄μΌ ν¨
λ°μ΄ν°λ² μ΄μ€κ° μ’ λ£λμ΄λ λ°μ΄ν°λ 물리μ μΈ μ μ₯μμ μ μ₯λμ΄ μ§μμ μΌλ‘ μ μ§λμ΄μΌ ν¨
[μ°Έκ³ ] https://ko.wikipedia.org/wiki/ACID
λͺ¨λ μμ μ μ΅μ’ μ μΌλ‘ λ°μ΄ν°λ² μ΄μ€μ λ°μνλ λͺ λ Ήμ΄
λ³κ²½λ λ΄μ©μ΄ λ°μ΄ν°λ² μ΄μ€μ μꡬμ μΌλ‘ μ μ₯
commit λͺ λ Ήμ μν β νλμ νΈλμ μ κ³Όμ μ μ’ λ£
β JPA APIλ₯Ό μ¬μ©ν commit κ³Όμ
β JPA κΈ°μ μ μ¬μ©ν λ°μ΄ν°λ² μ΄μ€μμ μΈν°λμ
μ λ΄λΆμ μΌλ‘λ JDBC APIλ₯Ό ν΅ν΄μ μ΄λ£¨μ΄μ§
βοΈ @Transactional
ν΄λμ€ λ 벨μ λΆμ΄λ©΄ ν΄λΉ ν΄λμ€ λ΄μ λͺ¨λ λ©μλμ νΈλμμ μ μ©λ¨
μ΄ μ λν μ΄μ μ΄ λΆμ ν΄λμ€μ λ©μλκ° νΈμΆλλ©΄ νΈλμμ μ΄ νλ μμ±
μ΄ μ λν
μ΄μ
μ΄ λΆμ λ©μλ λ΄μ λ€λ₯Έ λ©μλλ₯Ό νΈμΆνκ³ μμΌλ©΄ ν νΈλμμ
μΌλ‘ λ¬Άμ
β μμμ± μ μ©
(νλ μ€ν¨νλ©΄ λͺ¨λ μ€ν¨ν κ²μΌλ‘ κ°μ£Όνμ¬ rollback / λͺ¨λ μ±κ³΅ν΄μΌ commit )
β
[μ°Έκ³ ] https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html
βοΈ @Transactional
μ μ°μ μμ
βοΈ @Transactional
μ μ νΈλ¦¬λ·°νΈ
β ν΄λμ€ λ΄μ λ©μλκ° λ§μΌλ©΄ @Transactional
λ₯Ό ν΄λμ€ λ 벨μ λΆμ΄λ κ² λ°λμ§νκ³ , ν΄λμ€ λ΄μ μ‘°ννλ λ©μλκ° μ λ€λ©΄ @Transactional
λ₯Ό κ°κ°μ λΆμ΄λ κ² λ°λμ§
@Transactional(readOnly = true)
νΈλμμ μ ν΄λΉ λ©μλμ μ€μ μ readOnlyλ‘ μ€μ νλ κ²
commit μ JPA λ΄λΆμ μΌλ‘ μμμ± μ»¨ν
μ€νΈλ₯Ό flushνμ§ μμ
β flush μ²λ¦¬ / μ€λ
μ· μμ± λ±μ λΆνμν λμ μ€μ
β
β μ‘°ν λ©μλμλ readonly μμ±μ trueλ‘ μ§μ ν΄μ JPAκ° μ체μ μΌλ‘ μ±λ₯ μ΅μ ν κ³Όμ μ κ±°μΉλλ‘ νλκ²μ΄ μ’μ
( λ‘κ·Έλ₯Ό 보면 μλμ κ°μ΄ μμ±μ΄ readOnlyλ‘ λ°λλ κ±Έ νμΈν μ μμ β¬οΈ )
νΈλμμ
μ ν (Transaction Propagation)
β νΈλμμ
μ κ²½κ³μμ μ§ν μ€μΈ νΈλμμ
μ΄ μ‘΄μ¬ν λ λλ μ‘΄μ¬νμ§ μμ λ, μ΄λ»κ² λμν κ²μΈμ§ κ²°μ νλ λ°©μ
β
β propagation μ νΈλ¦¬λ·°νΈλ₯Ό ν΅ν΄μ μ€μ
β
βοΈ
propagation
μ νΈλ¦¬λ·°νΈ
Propagation.REQUIRED
β propagation μ νμ λν΄νΈ κ° / κ°μ₯ λ§μ΄ μ¬μ©λ¨
β μ§ν μ€μΈ νΈλμμ μ΄ μμΌλ©΄ μλ‘ μμ±νμ¬ μμ
β μ§ν μ€μΈ νΈλμμ μ΄ μμΌλ©΄ ν΄λΉ νΈλμμ μ μ°Έμ¬
β Propagation.REQUIRES_NEW
β μ΄λ―Έ μ§νμ€μΈ νΈλμμ κ³Ό 무κ΄νκ² μ νΈλμμ μμ
β κΈ°μ‘΄μ μ§νμ€μ΄λ νΈλμμ μ μ νΈλμμ μ΄ μ’ λ£λ λκΉμ§ μ€μ§
β Propagation.MANDATORY
β μ§νμ€μΈ νΈλμμ μ΄ μμΌλ©΄ μμΈ λ°μ
β Propagation.NOT_SUPPORTED
β νΈλμμ μ νμλ‘ νμ§ μμμ μλ―Έ
β μ§ν μ€μΈ νΈλμμ μ΄ μμΌλ©΄ λ©μλ μ€νμ΄ μ’ λ£λ λ κΉμ§ μ§νμ€μΈ νΈλμμ μ μ€μ§λλ©°, λ©μλ μ€νμ΄ μ’ λ£λλ©΄ νΈλμμ μ κ³μ μ§ν
β Propagation.NEVER
β νΈλμμ μ νμλ‘ νμ§ μμμ μλ―Έ
β μ§ν μ€μΈ νΈλμμ μ΄ μ‘΄μ¬ν κ²½μ°μλ μμΈλ₯Ό λ°μ
β
But, μμ λ³λ‘ νΈλμμ μ μλ‘ μμ±ν΄μΌ νλ€κ±°λ νΉμ μμ μλ νΈλμμ μ μ μ©νμ§ μλ λ±μ κ²½μ°κ° μλλΌλ©΄
@Transactional
μ λν μ΄μ λ§ μΆκ°ν΄λ 무방
β
[μ°Έκ³ ] https://docs.spring.io/spring-framework/docs/5.0.x/spring-framework-reference/data-access.html#tx-propagation
νΈλμμ
격리 λ 벨 (Isolation Level)
β νΈλμμ
μ 격리μ±μ΄ 보μ₯λμ΄μΌ ν¨
(λ€λ₯Έ νΈλμμ
μ μν₯μ μ£Όμ§ μκ³ , λ
립μ μΌλ‘ μ€νλμ΄μΌ ν¨)
β
βοΈ
Isolation
μ νΈλ¦¬λ·°νΈ
Isolation.DEFAULT
β λ°μ΄ν°λ² μ΄μ€μμ μ 곡νλ κΈ°λ³Έ κ°
β β Isolation.READ_UNCOMMITTED
β λ€λ₯Έ νΈλμμ μμ 컀λ°νμ§ μμ λ°μ΄ν°λ₯Ό μ½λ κ² νμ©
β β Isolation.READ_COMMITTED
β λ€λ₯Έ νΈλμμ μ μν΄ μ»€λ°λ λ°μ΄ν°λ₯Ό μ½λ κ² νμ©
β β Isolation.REPEATABLE_READ
β νΈλμμ λ΄μμ ν λ² μ‘°νν λ°μ΄ν°λ₯Ό λ°λ³΅ν΄μ μ‘°νν΄λ κ°μ λ°μ΄ν°κ° μ‘°νλλλ‘ ν¨
β β Isolation.SERIALIZABLE
β λμΌν λ°μ΄ν°μ λν΄μ λμμ λ κ° μ΄μμ νΈλμμ μ΄ μνλμ§ λͺ»νλλ‘ ν¨
β β β
β νΈλμμ μ 격리 λ 벨μ μΌλ°μ μΌλ‘ λ°μ΄ν°λ² μ΄μ€λ λ°μ΄ν°μμ€μ μ€μ λ 격리 λ 벨μ λ°λ₯΄λ κ²μ΄ κΆμ₯
π‘ μ²΄ν¬ μμΈ(checked exeption)λ rollbackμ΄ μ λ κΉ?
@Transactional
μ λν μ΄μ λ§ μΆκ°ν΄μλ rollbackμ΄ λμ§ μμ
( μμΈλ₯Ό catch ν΄μ ν΄λΉ μμΈλ₯Ό 볡ꡬν μ§ ννΌν μ§ λ±μ μ μ ν μμΈ μ λ΅μΌλ‘ 체ν¬ν΄μΌνκΈ° λλ¬Έμ )
Ex. Exception, SQLException, DataFormatException]
β
β λ³λμ μμΈ μ λ΅μ 지 νμκ° μλ€λ©΄,
@Transactional(rollbackFor = {SQLException.class, DataFormatException.class})
μ²λΌ ν΄λΉ μ²΄ν¬ μμΈλ₯Ό μ§μ μ§μ ν΄μ£Όκ±°λ
μΈμ²΄ν¬ μμΈ(unchecked exception)λ‘ κ°μΈμ rollbackμ΄ λμνλλ‘ ν μ μμ !
β AOP λ°©μ μ΄μ©νμ¬ λΉμ¦λμ€ λ‘μ§μμ μμ νΈλμμ μ μ© μ½λ μ체λ₯Ό κ°μΆλ λ°©μ
Config ν΄λμ€μ @Configuration
μ λν
μ΄μ
μΆκ°νμ¬ νΈλμμ
μ μ©μ μν Configuration
ν΄λμ€ μ μ
μμ±μμ TransactionManager
κ°μ²΄ DI
β
[μ°Έκ³ ] https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionManager.html
νΈλμμ
μ΄λλ°μ΄μ€μ© TransactionInterceptor
λΉ λ±λ‘
β TransactionInterceptor
λ₯Ό μ΄μ©ν΄ λμ ν΄λμ€ / μΈν°νμ΄μ€μ νΈλμμ
κ²½κ³ μ€μ λ° νΈλμμ
μ μ©μ ν μ μμ
( TransactionInterceptor
νμ
μ μ΄λλ°μ΄μ€ λ©μλ μμ± )
β
[μ°Έκ³ ] https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/interceptor/TransactionInterceptor.html
β
3-1. NameMatchTransactionAttributeSource
κ°μ²΄ μμ±
β
[μ°Έκ³ ] https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/interceptor/NameMatchTransactionAttributeSource.html
β
3-2. μ‘°ν λ©μλλ₯Ό μ μΈν κ³΅ν΅ νΈλμμ
μ νΈλ¦¬λ·°νΈ1 μμ±
β
3-3. μ‘°ν λ©μλμ μ μ©νκΈ° μν νΈλμμ
μ νΈλ¦¬λ·°νΈ2 μμ±
β
3-4. νΈλμμ
μ μ μ©ν λ©μλμ νΈλμμ
μ νΈλ¦¬λ·°νΈ 맀ν
β μ€μ ν νΈλμμ
μ νΈλ¦¬λ·°νΈλ Mapμ keyλ₯Ό λ©μλ μ΄λ¦ ν¨ν΄μΌλ‘ μΆκ°νκ³ κ°κ° νΈλμμ
μ μ νΈλ¦¬λ·°νΈ μΆκ°
β β
3-5. νΈλμμ
μ νΈλ¦¬λ·°νΈλ₯Ό μΆκ°ν Map κ°μ²΄λ₯Ό txAttributeSource.setNameMap(Map μ΄λ¦)
μΌλ‘ λ겨μ€
β
3-6. TransactionInterceptor
κ°μ²΄ μμ± ν, TransactionInterceptor
μ μμ±μ νλΌλ―Έν°λ‘ transactionManager
/txAttributeSource
μ λ¬νμ¬ λ¦¬ν΄
Advisor λΉ λ±λ‘
β
4-1. AspectJExpressionPointcut
κ°μ²΄ μμ±
β νΈλμμ
μ΄λλ°μ΄μ€μΈ TransactionInterceptor
λ₯Ό νκ² ν΄λμ€μ μ μ©νκΈ° μν΄ ν¬μΈνΈ μ»·μ μ§μ
β
4-2. ν¬μΈνΈ μ»· ννμμΌλ‘ ν΄λΉ ν΄λμ€λ₯Ό νκ² ν΄λμ€λ‘ μ§μ
β
4-3. DefaultPointcutAdvisor
μ μμ±μ νλΌλ―Έν°λ‘ ν¬μΈνΈμ»·κ³Ό μ΄λλ°μ΄μ€λ₯Ό μ λ¬νμ¬ λ¦¬ν΄
β return new DefaultPointcutAdvisor(pointcut μ΄λ¦, μ΄λλ°μ΄μ€ λ©μλ());
( H2 μΈλ©λͺ¨λ¦¬ DBμ κ²½μ° λΆμ° νΈλμμ μ΄ μ μμ μΌλ‘ λμνμ§ μκΈ°λλ¬Έμ μ€μ΅μμλ MySQL λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ© ! )
implementation 'mysql:mysql-connector-java' // MySQL 컀λ₯ν° μΆκ° implementation 'org.springframework.boot:spring-boot-starter-jta-atomikos' // λΆμ° νΈλμμ μ€ν μμ€μΈ atomikos μΆκ°
μλΈλ¦Ώ 컨ν
μ΄λ νκ²½μμ λΆμ° νΈλμμ
μ μ μ©νκΈ° μν΄μλ λ³λμ JTA νΈλμμ
맀λμ κ° νμ
β μ°λ¦¬λ κ°μ₯ λ§μ΄ μ¬μ©νλ μ€ν μμ€ JTA νΈλμμ
맀λμ νλ«νΌμΈ Atomikos
μ¬μ©
β μλμ κ°μ λ³λμ μΆκ° μ€μ μ΄ νμ
( λ‘컬 νΈλμμ
μ κ²½μ°, Spring Bootμ μλ ꡬμ±μ μ΄μ©νκΈ°λλ¬Έμ κ°λ°μκ° ν΄μΌ νλ μΌμ΄ λ³λ‘ μμμ )
ν΄λΉ λ°μ΄ν°λ² μ΄μ€μ λ§λ λ°μ΄ν°μμ€(Datasource) μμ±
κ° λ°μ΄ν°μμ€λ₯Ό JPAμ EntityManagerκ° μΈμνλλ‘ μ€μ
JTA TransactionManager μ€μ
JTA Platform μ€μ
β λ°±μ μ μν΄ νΉμ λ°μ΄ν°λ² μ΄μ€μ λ°μ΄ν°λ₯Ό λ€λ₯Έ λ°μ΄ν°λ² μ΄μ€λ‘ 볡μ νλ λ°©λ²
- κ°μ μ’ λ₯μ λ°μ΄ν°λ² μ΄μ€μΌ κ²½μ°
β 볡μ (Replication) κΈ°λ₯ μ΄μ©
β β - λ€λ₯Έ μ’ λ₯μ λ°μ΄ν°λ² μ΄μ€μΌ κ²½μ°
β μ ν리μΌμ΄μ μ μ€μΌμ₯΄λ§ κΈ°λ₯ μ΄μ©
β μ΄λ° κΈ°λ₯λ€μ κΈ°λ³Έμ μΌλ‘ μ§μνλ Apache NiFi κ°μ μ€ν μμ€ κΈ°μ λ μ¬μ© κ°λ₯
λκΈ°μ
β νΉμ μ½λλ₯Ό μν μλ£ν μ΄ν, μλμ€μ μ½λ μν
( μ½λμ μ°¨λ‘λλ‘ μλ£λ¨ )
λΉλκΈ°μ
β νΉμ μ½λλ₯Ό μννλ λμ€μ μλλ‘ κ³μ λ΄λ €κ°λ©° μν
( μμλ§ μ°¨λ‘λ‘ νκ³ μ½λμ μν μκ°μ λ°λΌ μλ£λλ μ½λμ μμκ° λ€λ¦ )
[μ°Έκ³ ] https://wakestand.tistory.com/235
[κ³Όμ μ°Έκ³ ]
https://www.baeldung.com/spring-events#publisher
https://sabarada.tistory.com/184
https://engkimbs.tistory.com/718
........................................................................................................................................................................................................
νΈλμμ
μ΄ μ΄λ»κ² μ μ©λλμ§ λ‘κ·Έ νμΈνκ³ μΆλ€λ©΄,
applictaion.yml
νμΌμ μλ μ½λ μΆκ°νκΈ° !
logging: level: org: springframework: orm: jpa: DEBUG
μμ κ°μ΄ λ‘κ·Έ λ 벨μ DEBUG λ λ²¨λ‘ μ€μ νλ©΄ JPA λ΄λΆμμ DEBUG λ‘κ·Έ λ 벨μ μ§μ ν λΆλΆμ λ‘κ·Έ νμΈ κ°λ₯ !
κ·Έλ¦¬κ³ μ»€λ° λ‘κ·Έλ₯Ό μ΄ν΄λ³΄κΈ° μν΄ ν¬μ€νΈλ§¨μΌλ‘ memberμ κ°μ postν ν λ‘κ·Έλ₯Ό 보면,
β¬οΈ νΈλμμ
μ μ¬μ©νκΈ° μν΄ JPAμ EntityManagerλ₯Ό μ΄κ³ μλ κ²μ μ μ μμ
β¬οΈ MemberServiceμ createMember()
λ©μλκ° νΈμΆλλ©΄μ μλ‘μ΄ νΈλμμ
μ΄ μμ±λκ³ μμμ μ μ μμ
β¬οΈ νΈλμμ μμ commitμ΄ μΌμ΄λκ³ νΈλμμ μ΄ μ’ λ£λμ΄ JPAμ EntityManagerλ₯Ό μ’ λ£νκ³ μμμ μ μ μμ
κ·Έλ¦¬κ³ λ‘€λ°± λ‘κ·Έλ₯Ό μ΄ν΄λ³΄κΈ° μν΄ MemberServiceμ creatMember()
λ©μλμ μ½λλ₯Ό μλμ κ°μ΄ λ°κΎΈκ³
ν¬μ€νΈλ§¨μΌλ‘ memberμ κ°μ postν ν λ‘κ·Έλ₯Ό 보면,
β¬οΈ νΈλμμ
μμ μλ¬κ° λνλ rollbackμ΄ μ μμ μΌλ‘ μλνλ κ²μ μ μ μμ
( λ°μ΄ν° ν
μ΄λΈμμ μ λ³΄κ° λ€μ΄κ°μ§ μμ ! )
........................................................................................................................................................................................................
μ½μμ°½μ λ‘κ·Έλ€μ 보기 νΈνκ² μμμ λ°κΎΈκ³ μΆλ€λ©΄,
applictaion.yml
νμΌμ μλ μ½λ μΆκ°νκΈ° !
spring: //μ΄λ―Έ μμ±λμ΄ μμ output: //μΆκ° ansi: //μΆκ° enabled: always //μΆκ°
κ·Έλ¬λ©΄ μλμ κ°μ΄ μλ‘λ¬λ‘ν λ‘κ·Έλ€μ λ³Ό μ μλ€ !
κ·Έλλ λ€λ₯Έ μ±ν°μ λΉν΄ νΈλμμ
λΆλΆμ κ·Έλλ κ°λ¨νκ² ν κ² κ°λ€ !
μ€μ΅ κ³Όμ κ° μ‘°κΈ μ΄λ ΅κΈ΄ νμ§λ§ μ΄ν΄λ₯Ό νλ μ¬μ κ³ κ΅¬νν λ΄μ©λ μ μ΄μ μ’μλ€ γ
γ
λ€μ μ±ν°λ νμ΄ν