[JPA] Transactional
Categories: Spring
Tags: JPA, Spring, Transaction, ์ค์ต
๐ ๊ฐ์ธ์ ์ธ ๊ณต๊ฐ์ผ๋ก ๊ณต๋ถ๋ฅผ ๊ธฐ๋กํ๊ณ ๋ณต์ตํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ธ๋ก๊ทธ์
๋๋ค.
์ ํํ์ง ์์ ์ ๋ณด๊ฐ ์์ ์ ์์ผ๋ ์ฐธ๊ณ ๋ฐ๋๋๋ค :๐ธ
[ํ๋ฆฐ ๋ด์ฉ์ ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๋ฉด ๋ณต๋ฐ์ผ์ค๊ฑฐ์์]
Transaction Intro
- ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋ ํต์ฌ์ ์ธ ์ญํ
- ์ด๋๋์ ๋ง๋ ์ปคํผ์ฃผ๋ฌธ ์์คํ
์์ ๋ฐ์ํ ์ ์๋ Transaction ์ฌ๋ก
- ์ฃผ๋ฌธ ์ค ๋คํธ์ํฌ ์ค๋ฅ๋ก ๊ฒฐ์ ์คํจํ๋๋ฐ DB์ ์ฃผ๋ฌธ์ด ์ ์๋ฑ๋ก ๋์ด ์ปคํผ ์๋งํผ ์คํฌํ๊ฐ ์ฐํ ๊ฒฝ์ฐ
- ๊ฒฐ์ ๋ฅผ ํ๋๋ฐ DB์ ์ ์ ๋ฑ๋ก์ด ๋์ง ์์ ํ์์ด ์ปคํผ๋ฅผ ๋ฐ์ง ๋ชปํ์ ๋
- ์ฃผ๋ฌธ์ ์ ์ ๋ฑ๋ก ๋์๋๋ฐ ์คํฌํ ํ์๋ง DB์ ์ ๋ฐ์ดํธ ํ๋ ์ค์ ์๋ฌ๊ฐ ๋ฐ์ํด์ ๋์ ์ด ๋์ง ์์์ ๊ฒฝ์ฐ
ACID ์์น
5์์ DB์์ ํ์ง๋ง ์ค์ํ๋๊น ํ๋ฒ ๋ ์ ๋ฆฌํด๋ด!
- ์์์ฑ(Atomicity)
- ํธ๋์ญ์ ์์์ ์์์ฑ์ด๋ ์์ ์ ๋ ์ด์ ์ชผ๊ฐค ์ ์์์ ์๋ฏธ
- ๋ฐ๋ผ์ ๋ ผ๋ฆฌ์ ์ผ๋ก ํ๋์ ์์ ์ผ๋ก ์ธ์ํด์ ๋ ๋ค ์ฑ๊ณตํ๋ ๊ฐ ๋ ๋ค ์คํจํ๋ ๊ฐ(All or Nothing)์ค์์ ํ๋๋ก๋ง ์ฒ๋ฆฌ๋๋ ๊ฒ์ด ๋ณด์ฅ๋์ด์ผ ํจ.
- ์ผ๊ด์ฑ(Consistency)
- ์ผ๊ด์ฑ์ ํธ๋์ญ์ ์ด ์๋ฌ ์์ด ์ฑ๊ณต์ ์ผ๋ก ์ข ๋ฃ๋ ๊ฒฝ์ฐ, ๋น์ฆ๋์ค ๋ก์ง์์ ์๋ํ๋ ๋๋ก ์ผ๊ด์ฑ ์๊ฒ ์ ์ฅ๋๊ฑฐ๋ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ์๋ฏธ
- ์ฃผ๋ฌธํ ์ปคํผ์ ์๋งํผ, ์คํฌํ ํ์๊ฐ ์ฆ๊ฐํ๋ค๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋ง๊ฒ ์ ์ฅ๋๊ฑฐ๋ ๋ณ๊ฒฝ๋์ด์ผ ํจ. ๋ง์ฝ์ 3์ด ์๋ ์ซ์๋ก ์ฆ๊ฐํ ๊ฐ์ด ์กฐํ๋๋ค๋ฉด ์ผ๊ด์ฑ์ ์๋ฐฐ๋๋ ๊ฒ
- ๊ฒฉ๋ฆฌ์ฑ(Isolation)
- ๊ฒฉ๋ฆฌ์ฑ์ ์ฌ๋ฌ ๊ฐ์ ํธ๋์ญ์ ์ด ์คํ๋ ๊ฒฝ์ฐ ๊ฐ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ์ด ๋์ด์ผ ํจ์ ์๋ฏธ
- ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ๊ฐ ์ปดํจํฐ์์ ์๋ ์์ ์ ํ๊ณ ์๊ณ , ๋์์ ๋ฎค์ง ํ๋ ์ด์ด๋ก ์์ ์ ๋ฃ๊ณ ์๋ค๋ฉด ์ฐ๋ฆฌ ๋์๋ ๋ณด์ด์ง ์์ง๋ง CPU๋ ์ ๋ ๊ฐ์ง ํ๋ก์ธ์ค๋ฅผ ์์ฃผ ๋น ๋ฅธ ์๋๋ก ๋ฒ๊ฐ์๊ฐ๋ฉด์ ์คํ์ ์ํค๋ ๊ฒ
- ์ด์ฒ๋ผ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ญ์ ์ฑ๋ฅ ํฅ์์ ๋ชฉ์ ์ผ๋ก ํ ๊ฐ ์ด์์ ํธ๋์ญ์ ์ ๋ฒ๊ฐ์๊ฐ๋ฉด์ ์ฒ๋ฆฌํ ์ ์๋๋ฐ, ์ด ๊ฒฝ์ฐ ๊ฐ ํธ๋์ญ์ ์ด ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ํฅ์ ์ฃผ์ง ์๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ์ด ๋์ด์ผ ํ๋ค๋ ๊ฒ์ด ๋ฐ๋ก ๊ฒฉ๋ฆฌ์ฑ(Isolation).
- ์ง์์ฑ(Durability)
-
ํธ๋์ญ์ ์ด ์๋ฃ๋๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ ์ง์๋์ด์ผ ํ๋ค๋ ์๋ฏธ
-
์ฆ, ์ง์์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ข ๋ฃ๋์ด๋ ๋ฐ์ดํฐ๋ ๋ฌผ๋ฆฌ์ ์ธ ์ ์ฅ์์ ์ ์ฅ๋์ด ์ง์์ ์ผ๋ก ์ ์ง๋์ด์ผ ํ๋ค๋ ์๋ฏธ
-
ํธ๋์ญ์ ์ปค๋ฐ(commit)๊ณผ ๋กค๋ฐฑ(rollback)
Commit
- ์ปค๋ฐ(commit)์ ๋ชจ๋ ์์ ์ ์ต์ข ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ํ๋ ๋ช ๋ น์ด๋ก์จย commit ๋ช ๋ น์ ์ํํ๋ฉด ๋ณ๊ฒฝ๋ ๋ด์ฉ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๊ตฌ์ ์ผ๋ก ์ ์ฅ๋จ.
- ๋ง์ฝ commit ๋ช ๋ น์ ์ํํ์ง ์์ผ๋ฉด ์์ ์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ต์ข ์ ์ผ๋ก ๋ฐ์๋์ง ์์
- commit ๋ช ๋ น์ ์ํํ๋ฉด,ย ํ๋์ ํธ๋์ ์ ๊ณผ์ ์ ์ข ๋ฃ
๋กค๋ฐฑ(rollback)
- ๋กค๋ฐฑ(rollback)์ ์์ ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋, ํธ๋์ญ์ ๋ด์์ ์ํ๋ ์์ ๋ค์ ์ทจ์ํ๋ค.
- ๋ฐ๋ผ์ ํธ๋์ญ์ ์์ ์ด ์ ์ ์ํ๋ก ๋๋์ ๊ฐ๊ฒ ๋จ.
์ธ๋ฉ๋ชจ๋ฆฌ DB ํน์ฑ์ (H2๋ ์ธ๋ฉ๋ชจ๋ฆฌ DB๋ค) , ์ธ๋ฉ๋ชจ๋ฆฌ DB๋? โ
JPA์ tx.commit() ๋ด๋ถ
๐ JPA tx.commit() ํธ์ถ ๊ณผ์ ์ดํด๋ฅผ ์ํ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ ๊ด๊ณ๋
โ
- ์ถ์ํ๋์ด์์ด์ ๊ตฌํ์ฒด๋ฅผ ์ญ ์ง๋๊ฐ๋ค๋ณด๋ฉด ๋ง์ง๋ง์ Command๊ฐ ์์.
- ์ฐ๋ฆฌ๊ฐ JPA API๋ฅผ ์ฌ์ฉํด์ commit์ ์ํํ๋ ์์ ์ ๋๋ฌด๋๋ ๊ฐ๋จํ ์์ ์ธ๋ฐ, ๋ด๋ถ์ ์ผ๋ก๋ ์์ฃผ ๋ณต์กํ ๊ณผ์ ์ ๊ฑฐ์ณ์ ์ต์ข ์ ์ผ๋ก commit ๋ช ๋ น์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ฌ
ํ๋์ ์์ ๋จ์๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌํด์ผ ๋๋ ์ํฉ์์๋ ์ด๋ค ์์ผ๋ก ํธ๋์ญ์ ์ ์ ์ฉํ๋ฉด ์ข์์ง์ ๋ํด์ ๊ผญ ๊ณ ๋ฏผํด๋ณด๊ธฐ
์ ์ธํ ๋ฐฉ์์ ํธ๋์ญ์
๐ ์์ฝ
โ๏ธ Class level๊ณผ Method level์ ์ค์ ๊ฐ๋ฅ, ๋ ๋ค ์ค์ ํ์ ๊ฒฝ์ฐ์๋ Method๊ฐ ์ฐ์ ์์๋ฅผ ๊ฐ์ง๊ฒ ๋๋ค
โ๏ธ Checked exception๋ @Transactional ์ ๋ํ ์ด์ ๋ง ์ถ๊ฐํด์๋ rollback์ด ๋์ง ์์ โ ์์ฑ์ rollbackFor๋ก ์ง์ ํด ์ฃผ์ด์ผ ํจ
โ๏ธ Ex ) @Transactional(rollbackForย = {SQLException.class, DataFormatException.class})
์ ๋ํ ์ด์ ๋ฐฉ์ @Transactional
-
class level์ ์ ์ฉ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
... **import org.springframework.transaction.annotation.Transactional;** @Service @Transactional // (1) public class MemberService { private final MemberRepository memberRepository; public MemberService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } public Member createMember(Member member) { verifyExistsEmail(member.getEmail()); return memberRepository.save(member); } ... }
- MemberRepository์ ๊ธฐ๋ฅ์ ์ด์ฉํ๋ ๋ชจ๋ ๋ฉ์๋์ ํธ๋์ญ์ ์ด ์ ์ฉ
-
JPA ๋ก๊ทธ๋ ๋ฒจ ์ค์
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
spring: h2: console: enabled: true path: /h2 datasource: url: jdbc:h2:mem:test jpa: hibernate: ... ... logging: # (1) ๋ก๊ทธ ๋ ๋ฒจ ์ค์ level: org: springframework: orm: jpa: DEBUG
-
์ฝ์ log ํ์ธ
- application ์คํํ์ฌ Postman์ผ๋ก ํ์ ๋ฑ๋ก ํ log ํ์ธ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
... 2024-06-25 22:19:55.876 DEBUG 46820 --- [nio-8080-exec-4] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1398140194<open>)] for JPA transactio //(1) : **Creating new transaction with name** [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save] : PROPAGATION_REQUIRED,ISOLATION_DEFAULT //(2) 2024-06-25 22:19:55.887 DEBUG 46820 --- [nio-8080-exec-4] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit 2024-06-25 22:19:55.887 DEBUG 46820 --- [nio-8080-exec-4] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1398140194<open>)] 2024-06-25 22:19:55.899 DEBUG 46820 --- [nio-8080-exec-4] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction //(3) //(4) 2024-06-25 22:19:55.910 DEBUG 46820 --- [nio-8080-exec-4] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewIntercepto
- (1) : CoffeeService์ createCoffee() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด์ ์๋ก์ด ํธ๋์ญ์ ์ด ์์ฑ
- (2) : ํธ๋์ญ์ ์์ commit์ด ์ผ์ด๋๊ณ ์์
- (3) : ํธ๋์ญ์ ์ด ์ข ๋ฃ๋จ
- (4) : JPA์ EntityManager๋ฅผ ์ข ๋ฃ
-
roolback ๋์ ์ ๋ฌด ํ์ธ
-
createMember() ๋ฉ์๋์์ ํ์ ์ ๋ณด ์ ์ฅํ๊ณ ๋ฉ์๋๊ฐ ์ข ๋ฃ๋๊ธฐ ์ ์ ๊ฐ์ ๋ก ์์ธ ๋ฐ์์ํค๊ธฐ.
๋กค๋ฐฑ ํ ์์ธ ๋์ง.
-
Checked Exception
-
Checked ์์ธ๋ก ํ ๋ ค๋ฉด ์คํ์กฐ์ฐจ ๋์ง ์๊ธฐ ๋๋ฌธ์ throw๋ก ๋์ ธ์ผ ์คํํ ์ ์์.
-
์ด ์์ธ๋ ๋กค๋ฐฑํด์ฃผ์ธ์ ๋ผ๊ณ attribute ๋ฃ์ด์ผ ํจ โ ์ ๋ฃ์ผ๋ฉด ๋กค๋ฐฑ ์๋จ!
Class Level ๊ณผ Method Level์ ์ ์ฉ์
- ํด๋์ค ๋ ๋ฒจ๊ณผ ๋ฉ์๋ ๋ ๋ฒจ์ ํธ๋์ญ์ ์ ์ฉ ์์
- ํด๋์ค ๋ ๋ฒจ์๋ง
@Transactional
์ด ์ ์ฉ๋ ๊ฒฝ์ฐ- ํด๋์ค ๋ ๋ฒจ์
@Transactional
์ ๋ํ ์ด์ ์ด ๋ฉ์๋์ ์ผ๊ด ์ ์ฉ๋จ
- ํด๋์ค ๋ ๋ฒจ์
- ํด๋์ค ๋ ๋ฒจ๊ณผ ๋ฉ์๋ ๋ ๋ฒจ์ ํจ๊ป ์ ์ฉ๋ ๊ฒฝ์ฐ
- ๋ฉ์๋ ๋ ๋ฒจ์
@Transactional
์ ๋ํ ์ด์ ์ด ์ ์ฉ๋จ - ๋ง์ฝ ๋ฉ์๋ ๋ ๋ฒจ์
@Transactional
์ ๋ํ ์ด์ ์ด ์ ์ฉ๋์ง ์์์ ๊ฒฝ์ฐ, ํด๋์ค ๋ ๋ฒจ์@Transactional
์ ๋ํ ์ด์ ์ด ์ ์ฉ
- ๋ฉ์๋ ๋ ๋ฒจ์
- ํด๋์ค ๋ ๋ฒจ์๋ง
-
๋ฉ์๋๋ ๋ฒจ์์ @Transactional(readOnly = true) ์ ์ฉ
โ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ค์ ํ๋ ๊ฒ :
โ ์ด์ : commit์ด ๋์ง ์์ ์์์ฑ ์ปจํ ์คํธ์ flush๋ ํ์ง ์๊ณ ์ค๋ ์ท์ ์์ฑํ์ง ์์ผ๋ฏ๋ก ๋ถํ์ํ ์ถ๊ฐ๋์์ ์ค์ผ ์ ์์.
โ ์ฆ ์กฐํ ๋ฉ์๋์๋ readOnly=true ๋ก ์ค์ ํ์ฌ JPA๊ฐ ์์ฒด์ ์ผ๋ก ์ฑ๋ฅ ์ต์ ํ ๊ณผ์ ์ ๊ฑฐ์น๋๋ก ํ๋ ๊ฒ์ ๊ถ์ฅ!
์ฌ๋ฌ ์์ ์ด ํ๋์ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ผ ๊ฒฝ์ฐ
โ
- OrderService์์ createOrder() ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฒฝ์ฐ, ๋ด๋ถ์์ ์ฃผ๋ฌธ ์ ๋ณด ์ ์ฅ์ ์ํ ํธ๋์ญ์ ์ด ํ๋ ์์๋๋ฉฐ, ๋ค์์ผ๋ก memberService.updateStamp() ๋ฉ์๋ ํธ์ถ์ ํตํด์ MemberService์์ ์คํฌํ ์ ๋ฐ์ดํธ๋ฅผ ์ํ ํธ๋์ญ์ ์ด ํ๋ ๋ ์์๋จ
- ๋ง์ฝ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋๋ค๋ฉด updateStamp() ๋์์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ์คํฌํ ์ซ์๋ ์ ๋ฐ์ดํธ๋์ง ์์๋๋ฐ ์ฃผ๋ฌธ ์ ๋ณด๋ ์ ์ฅ๋๋ ์์น ์๋ ์ํฉ์ด ๋ฐ์ํจ
โ
- ํธ๋์ญ์
์ด ํ๋๋ก ๋ฌถ์ด๋ฉด
MemberService
์updateStamp(
) ๋ฉ์๋ ์์ ์ ์ฒ๋ฆฌํ๋ ๋์ค์ ์์ธ๊ฐ ๋ฐ์ํด๋ ๋ ํด๋์ค์์ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฉ์๋๋ค์ด ๋ชจ๋ ํ๋์ ํธ๋์ญ์ ๊ฒฝ๊ณ ๋ด์ ์์ผ๋ฏ๋ก ๋ชจ๋ rollbacK ๋จ
Attribute ์ค์ ์ผ๋ก Transaction ์ ํ์ ๊ฒฉ๋ฆฌ๊ฐ ๊ฐ๋ฅ.
๐ ํธ๋์ญ์ ์ ํ (Transaction Propagation)
ํธ๋์ญ์ ์ ๊ฒฝ๊ณ์์ ์งํ ์ค์ธ ํธ๋์ญ์ ์ด ์กด์ฌํ ๋ ๋๋ ์กด์ฌํ์ง ์์ ๋, ์ด๋ป๊ฒ ๋์ํ ๊ฒ์ธ์ง ๊ฒฐ์ ํ๋ ๋ฐฉ์์ ์๋ฏธ
- @Transactional(propagation = Propagation.REQUIRED)
- ํ์ฌ ์งํ ์ค์ธ ํธ๋์ญ์ ์ด ์กด์ฌํ๋ฉด ํด๋น ํธ๋์ญ์ ์ ์ฌ์ฉํ๊ณ , ์กด์ฌํ์ง ์์ผ๋ฉด ์ ํธ๋์ญ์ ์ ์์ฑํ๋๋ก ํด์ค
- ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ propagation ์ ํ์ ๋ํดํธ ๊ฐ
- @Transactional(Propagation.REQUIRES_NEW)
- ์ด๋ฏธ ์งํ ์ค์ธ ํธ๋์ญ์ ๊ณผ ๋ฌด๊ดํ๊ฒ ์๋ก์ด ํธ๋์ญ์ ์ด ์์
- ๊ธฐ์กด์ ์งํ ์ค์ด๋ ํธ๋์ญ์ ์ ์๋ก ์์๋ ํธ๋์ญ์ ์ด ์ข ๋ฃํ ๋๊น์ง ์ค์ง๋จ
- @Transactional(Propagation.MANDATORY)
- ์งํ ์ค์ธ ํธ๋์ญ์ ์ด ์์ผ๋ฉด ์์ธ๋ฅผ ๋ฐ์์ํด
- @Transactional(Propagation.NOT_SUPPORTED)
- ํธ๋์ญ์ ์ ํ์๋ก ํ์ง ์์์ ์๋ฏธ
- ์งํ ์ค์ธ ํธ๋์ญ์ ์ด ์์ผ๋ฉด ๋ฉ์๋ ์คํ์ด ์ข ๋ฃ๋ ๋๊น์ง ์งํ ์ค์ธ ํธ๋์ญ์ ์ ์ค์ง๋๋ฉฐ, ๋ฉ์๋ ์คํ์ด ์ข ๋ฃ๋๋ฉด ํธ๋์ญ์ ์ ๊ณ์ ์งํ
- @Transactional(Propagation.NEVER)
- ํธ๋์ญ์ ์ ํ์๋ก ํ์ง ์์์ ์๋ฏธ
- ์งํ ์ค์ธ ํธ๋์ญ์ ์ด ์กด์ฌํ ๊ฒฝ์ฐ์๋ ์์ธ๋ฅผ ๋ฐ์์ํด
๐ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ(Isolation Level)
ํธ๋์ญ์
์ ๋ค๋ฅธ ํธ๋์ญ์
์ ์ํฅ์ ์ฃผ์ง ์๊ณ , ๋
๋ฆฝ์ ์ผ๋ก ์คํ๋์ด์ผ ํ๋ ๊ฒฉ๋ฆฌ์ฑ์ด ๋ณด์ฅ๋์ด์ผ ํ๋๋ฐ Spring์ ์ด๋ฌํ ๊ฒฉ๋ฆฌ์ฑ์ ์กฐ์ ํ ์ ์๋ ์ต์
์ @Transactional
์ ๋ํ
์ด์
์ isolation ์ ํธ๋ฆฌ๋ทฐํธ๋ฅผ ํตํด ์ ๊ณตํจ
-
@Transactional (Isolation.DEFAULT)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ๊ฐ
-
@Transactional(Isolation.READ_UNCOMMITTED) ๋ค๋ฅธ ํธ๋์ญ์ ์์ ์ปค๋ฐํ์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒ์ ํ์ฉํจ
-
@Transactional(Isolation.READ_COMMITTED) ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ํด ์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒ์ ํ์ฉํจ
-
@Transactional(Isolation.REPEATABLE_READ) ํธ๋์ญ์ ๋ด์์ ํ ๋ฒ ์กฐํํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํด์ ์กฐํํด๋ ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์กฐํ๋๋๋ก ํจ
-
@Transactional(Isolation.SERIALIZABLE) ๋์ผํ ๋ฐ์ดํฐ์ ๋ํด์ ๋์์ ๋ ๊ฐ ์ด์์ ํธ๋์ญ์ ์ด ์ํ๋์ง ๋ชปํ๋๋ก ํจ
ํธ๋์ญ์ ์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์ ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋ฐ์ดํฐ์์ค์ ์ค์ ๋ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์ ๋ฐ๋ฅด๋ ๊ฒ์ด ๊ถ์ฅ๋๋ฏ๋ก, ์ด๋ฌํ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์ด ์๋ค๊ณ ์ดํดํ๋ฉด ๋๋ค.
AOP ๋ฐฉ์์ ํธ๋์ญ์ ์ ์ฉ
๋น์ฆ๋์ค ๋ก์ง์ ์ ์ฉํ์ง ์๊ณ , ํธ๋์ญ์ ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.*;
import java.util.HashMap;
import java.util.Map;
// (1)
@Configuration
public class TxConfig {
private final TransactionManager transactionManager;
// (2)
public TxConfig(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Bean
public TransactionInterceptor txAdvice() {
NameMatchTransactionAttributeSource txAttributeSource =
new NameMatchTransactionAttributeSource();
// (3)
RuleBasedTransactionAttribute txAttribute =
new RuleBasedTransactionAttribute();
txAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// (4)
RuleBasedTransactionAttribute txFindAttribute =
new RuleBasedTransactionAttribute();
txFindAttribute.setPropagationBehavior(
TransactionDefinition.PROPAGATION_REQUIRED);
txFindAttribute.setReadOnly(true);
// (5)
Map<String, TransactionAttribute> txMethods = new HashMap<>();
txMethods.put("find*", txFindAttribute);
txMethods.put("*", txAttribute);
// (6)
txAttributeSource.setNameMap(txMethods);
// (7)
return new TransactionInterceptor(transactionManager, txAttributeSource);
}
@Bean
public Advisor txAdvisor() {
// (8)
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* com.codestates.coffee.service." +
"CoffeeService.*(..))");
return new DefaultPointcutAdvisor(pointcut, txAdvice()); // (9)
}
}
AOP ๋ฐฉ์์ผ๋ก ํธ๋์ญ์ ์ ์ ์ฉํ๋ ์์
-
AOP ๋ฐฉ์์ผ๋ก ํธ๋์ญ์ ์ ์ ์ฉํ๊ธฐ ์ํ Configuration ํด๋์ค ์ ์
(1)๊ณผ ๊ฐ์ด @Configuration ์ ๋ํ ์ด์ ์ ์ถ๊ฐํ๋ฉฐ Configuration ํด๋์ค๋ฅผ ์ ์
-
TransactionManager DI
์ ํ๋ฆฌ์ผ์ด์ ์ ํธ๋์ญ์ ์ ์ ์ฉํ๊ธฐ ์ํด์๋ TransactionManager ๊ฐ์ฒด๊ฐ ํ์ โ (2)์ ๊ฐ์ด TransactionManager ๊ฐ์ฒด๋ฅผ DI ๋ฐ์ต๋๋ค.
-
ํธ๋์ญ์ ์ด๋๋ฐ์ด์ค์ฉ TransactionInterceptor ๋น ๋ฑ๋ก
Spring์์๋ TransactionInterceptor๋ฅผ ์ด์ฉํด์ ๋์ ํด๋์ค ๋๋ ์ธํฐํ์ด์ค์ ํธ๋์ญ์ ๊ฒฝ๊ณ๋ฅผ ์ค์ ํ๊ณ ํธ๋์ญ์ ์ ์ ์ฉํ ์ ์๋ค.
- ํธ๋์ญ์
์ ํธ๋ฆฌ๋ทฐํธ ์ง์
- ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ๋ ๋ฉ์๋ ์ด๋ฆ ํจํด์ ๋ฐ๋ผ ๊ตฌ๋ถํด์ ์ ์ฉ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ (3), (4)์ ๊ฐ์ด ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ค์ ํ ์ ์๋ค.
- (3)์ ์กฐํ ๋ฉ์๋๋ฅผ ์ ์ธํ ๊ณตํต ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ์ด๊ณ , (4)๋ ์กฐํ ๋ฉ์๋์ ์ ์ฉํ๊ธฐ ์ํ ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ
- ํธ๋์ญ์
์ ์ ์ฉํ ๋ฉ์๋์ ํธ๋์ญ์
์ ํธ๋ฆฌ๋ทฐํธ ๋งคํ
- ์ค์ ํ ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ๋ (5)์ ๊ฐ์ด Map์ ์ถ๊ฐํ๋๋ฐ, Map์ key๋ฅผ ๋ฉ์๋ ์ด๋ฆ ํจํด์ผ๋ก ์ง์ ํด์ ๊ฐ๊ฐ์ ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ถ๊ฐ
- ํธ๋์ญ์ ์ ํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ถ๊ฐํ Map ๊ฐ์ฒด๋ฅผ (6)๊ณผ ๊ฐ์ด txAttributeSource.setNameMap(txMethods)์ผ๋ก ๋๊ฒจ์ค
- TransactionInterceptor ๊ฐ์ฒด ์์ฑ
- (7)๊ณผ ๊ฐ์ด TransactionInterceptor์ ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ก transactionManager์ txAttributeSource๋ฅผ ์ ๋ฌ
- ํธ๋์ญ์
์ ํธ๋ฆฌ๋ทฐํธ ์ง์
-
Advisor ๋น ๋ฑ๋ก
- ํฌ์ธํธ ์ปท ์ง์
- ์ด์ ํธ๋์ญ์
์ด๋๋ฐ์ด์ค์ธ
TransactionInterceptor
๋ฅผ ํ๊น ํด๋์ค์ ์ ์ฉํ๊ธฐ ์ํด ํฌ์ธํธ ์ปท์ ์ง์ - (8)๊ณผ ๊ฐ์ด AspectJExpressionPointcut ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ, ํฌ์ธํธ ์ปท ํํ์์ผ๋ก CoffeeService ํด๋์ค๋ฅผ ํ๊น ํด๋์ค๋ก ์ง์
- ์ด์ ํธ๋์ญ์
์ด๋๋ฐ์ด์ค์ธ
-
Advisor ๊ฐ์ฒด ์์ฑ
๋ง์ง๋ง์ผ๋ก (9)์ ๊ฐ์ด
DefaultPointcutAdvisor
์ ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ก ํฌ์ธํธ์ปท๊ณผ ์ด๋๋ฐ์ด์ค๋ฅผ ์ ๋ฌํด ์ค๋ค.
- ํฌ์ธํธ ์ปท ์ง์
-
AOP๊ฐ ์ ์ฉ๋์ด์๋ค๋ ๊ฒ์ ํ๋ก์ํจํด์ด ์ ์ฉ๋์ด์๋ค๋๊ฒ.
-
ํ๋ก์๊ฐ์ฒด๋ ์๋ณธ๊ฐ์ฒด์ ๋ฌ๋ฆฌ ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํฌํจ๋์ด์์.
-
SPRING AOP๋ ๊ฐ์์ ํ๋ก์๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ค๊ฐ์ ๋์ ์ฑ ํ ํ๋ก์๊ฐ์ฒด๊ฐ ์คํ๋จ โ ์๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ง ์๊ณ ์์ฒญ์ด ์์ ๋ ๋์ ์ผ๋ก ๋ง๋ฌ. ๊ฐ์์ ์ธ์์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ค์ฐ๋ฉด ์ง์๋ฒ๋ฆผ
-
๋ด๋ถ์ ์ผ๋ก GCLIB๋ผ๋ ๊ธฐ์ ์ ์ฌ์ฉ,,
-
AOP๋ฅผ ์จ์ TRANSACTION์ ์ฌ์ฉํ๊ณ ์๋ค๋ ๊ฒ์ ์์์ผ ํจ. (Spring AOP โ SPRING Transaction)
-
ํ๋ก์๋ ์๋จ์ ๋จผ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ ์ฒ๋ฆฌํ๋ ๊ฐ์์ ์๋ฒ, ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ๊ฒ๋ ํ๋ก์ - AOP๊ฐ ์ ์ฉ๋ ๊ฒ.
(์ฐธ๊ณ ) Springboot์ ์ฌ์ฉํ์ง ์์ ๊ฒฝ์ฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Configuration
@EnableTransactionManagement
public class JpaConfig{
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
final LocalContainerEntityManagerFactoryBean em =
new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
...
...
return em;
}
// (1)
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
...
...
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(){
JpaTransactionManager transactionManager
= new JpaTransactionManager(); // (2)
transactionManager.setEntityManagerFactory(
entityManagerFactoryBean().getObject() );
return transactionManager;
}
}
- (1)๊ณผ ๊ฐ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์๋ Datasource๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์
- Spring์์ ํธ๋์ญ์
์ ๊ธฐ๋ณธ์ ์ผ๋ก
PlatformTransactionManager
์ ์ํด ๊ด๋ฆฌ๋๋ฉฐ,PlatformTransactionManager
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ ํด๋น ๋ฐ์ดํฐ ์ก์ธ์ค ๊ธฐ์ ์ ๋ง๊ฒ ์ ์ฐํ๊ฒ ํธ๋์ญ์ ์ ์ ์ฉํ ์ ์๋๋ก ์ถ์ํ๋์ด ์์ - ๋ฐ์ดํฐ ์ก์ธ์ค ๊ธฐ์ ์ด JPA์ด๊ธฐ ๋๋ฌธ์ (2)์ ๊ฐ์ด
PlatformTransactionManager
์ ๊ตฌํ ํด๋์ค์ธJpaTransactionManager
๋ฅผ ์ฌ์ฉ
Leave a comment