DB ํธ๋์ญ์ ๊ณผ ์ปค๋ฅ์ ์ดํดํ๊ธฐ
by JiwonDevhttps://www.youtube.com/watch?v=urpF7jwVNWs&list=PLwouWTPuIjUg0dmHoxgqNXyx3Acy7BNCz&index=6
# ํธ๋์ญ์ ์ ๊ฐ๋
- ์ฌ๋ฌ ์ฝ๊ธฐ/์ฐ๊ธฐ๋ฅผ ๋ ผ๋ฆฌ์ ์ผ๋ก ํ๋๋ก ๋ฌถ์ ๊ฒ
- ๋ชจ๋ ์ ์ฉ๋๊ฑฐ๋(Commit) ๋ชจ๋ ์ทจ์๋๊ฑฐ๋(Rollback)
- ACID (์์์ฑ, ์ผ๊ด์ฑ, ๋ ๋ฆฝ์ฑ, ์ง์์ฑ)
- ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ๋ํ ๋ฌธ์ ๋ฅผ DB๊ฐ ๋์ ํด์ค
# ํธ๋์ญ์ ๋ฒ์๋ ์ปค๋ฅ์ ์ ๋ฐ๋ผ๊ฐ๋ค.
- [app1] ์ 5. SQL์ ์คํํ๋ค๊ฐ ์ค๋ฅ๋ฐ์ -> 6.Rollback
- [app1]์์ ์คํํ [4.method]๋ ๋กค๋ฐฑ๋ฌ์ผ๋ฉด ์ข๊ฒ ์
- ํ์ง๋ง ํ์ค์? ๋กค๋ฐฑ ๋์ง ์์. DB์ ๋ฐ์๋์ด์์.
# ํธ๋์ญ์ ์ ํ
์ฌ๋ฌ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋, ํ๋์ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒํด์ผํ ๊น => ํธ๋์ญ์ ์ ํ
2021.08.18 - [Backend/Spring Core] - @Transactional ์ ๋์์๋ฆฌ, ํธ๋์ญ์ ๋งค๋์
#Global Transaction (๊ฑฐ์ ์ฌ์ฉํ์ง ์์)
๊ทธ๋๋ง ๊ฐ์ DB์์ ์ด๋ฐ๊ฑฐ๋ฉด ๋คํ์ด๋ค. ๋ง์ฝ ์ธ๋ถ API๋ฅผ ์ฌ์ฉํ๋ค๊ฐ ๋กค๋ฐฑ์ด ํฐ์ง๋ค๋ฉด?
@ Global Transaction
- ๋ ๊ฐ ์ด์์ ์์ (DB, ๋ฉ์์งํ)๋ฅผ ํ ํธ๋์ญ์ ์ ๋ฌถ์ด์ ์ฒ๋ฆฌ
- ๊ฐ ์์์ด 2PC(2-phase commit)์ ์ง์ํด์ผํจ
- Global Tansaction manager๊ฐ ํ์
- ์์ ์์ ์ ๊ฐ์ ๋ ๊ฐ ์ด์์ ์์ฐ์์ ํธ๋์ญ์ ์ฒ๋ฆฌ๊ฐ ์ฌ์์ง
๊ทผ๋ฐ ์ ์์ฐ๋์? => ์ฑ๋ฅ์ด ๊ตฌ๋ ค์ง. MSA ๊ตฌ์กฐ์์๋ ์์ ์ฌ์ฉ๋ถ๊ฐ๋ฅ
์ด๋ฒคํธ, ๋น๋๊ธฐ ๋ฉ์์ง๊ณผ ๊ฐ์ ๋ค๋ฅธ์๋จ์ด ๋ ํ์ค์ ์ด๋ค.
# ํธ๋์ญ์ ๊ฒฉ๋ฆฌ
2021.08.10 - [๊ธฐ๋ณธ ์ง์/CS ๊ธฐ๋ณธ์ง์] - ํธ๋์ญ์ ๊ฒฉ๋ฆฌ์์ค(DB Isolation Level)
๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ ๊ทผํ๊ฒ ๋๋ค๋ฉด?
- ๋ด๋น์๋ ๋ฐ๋์ 1๋ช ์ด์์ด์ด์ผ ํ๋ค.
- ๋ด๋น์๋ ํด๊ทผํ๊ธฐ ์ , DB์ ๋ค๋ฅธ ๋ด๋น์๊ฐ ์๋์ง ํ์ธ ํ ํด๊ทผํด์ผํ๋ค.
- ๊ทผ๋ฐ ์๋์ ๊ฐ์ ๋ฌธ์ ๊ฐ ํฐ์ง๋ค๋ฉด?
# ๊ฒฝ์ ์ํ (Race Condition), ๋์์ฑ ๋ฌธ์
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ : ํธ๋์ญ์ ์ ์๋ก ๊ฒฉ๋ฆฌํด์ ๋ค๋ฅธ ํธ๋์ญ์ ์ด ์ํฅ ์ฃผ์ง ๋ชปํ๊ฒ ํจ.
- ๊ทธ๋ฅ ์์๋๋ก ์คํํ๋ฉด ์๋์? => ํ ๋ฒ์ ํ ๊ฐ์ ํธ๋์ญ์ ๋ง ์ฒ๋ฆฌ๊ฐ๋ฅ. ์ฑ๋ฅ์ด ๊ตฌ๋ฆผ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ ์ฝ๊ธฐ
@ ๋ฌธ์ 1: ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ ์ฝ๊ธฐ (dirty read)
@ ๋ฌธ์ 2: ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ ๋ฎ์ด์ฐ๊ธฐ (dirty write)
๋ฌธ์ 1,2๋ Read Committed๋ก ํด๊ฒฐ ๊ฐ๋ฅ
- ์ปค๋ฐ๋ ๊ฐ๊ณผ ํธ๋์ญ์ ์งํ ์ค์ธ ๊ฐ์ ๋ฐ๋ก ๋ณด๊ด (์ปค๋ฐ ๋ฐ์ดํฐ๋ง ์ฝ๊ธฐ)
- ํ ๋จ์ ์ ๊ธ ์ฌ์ฉ, ํด๋น ํ์ ์์ ํ๋ ํธ๋์ญ์ ์ด ๋๋ ๋ ๊น์ง ๋๊ธฐ (์ปค๋ฐ ๋ฐ์ดํฐ๋ง ์ฐ๊ธฐ)
@ ๋ฌธ์ 3: ์ฝ๋ ๋์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ1 (read skew, ์ฝ๋ ์์ ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋)
๋ฌธ์ 3์ Repeatable Read๋ก ํด๊ฒฐ ๊ฐ๋ฅ
ํธ๋์ญ์ ๋์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฒ ํ๋ฉด ๋จ. ๊ตฌํ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์
๊ตฌํ ์: MVCC(Multi-Version Concurrency Control)
@ ๋ฌธ์ 4: ๋ณ๊ฒฝ ์ ์ค (lost Update)
๋ฌธ์ 4 ํด๊ฒฐ์ฑ
- DB๊ฐ ์ง์ํ๋ ์์์ (atomic) ์ฐ์ฐ๋ง ์ฌ์ฉ
- ๋ช ์์ ์ธ ์ ๊ธ ์ฌ์ฉ (select ... for update)
- CAS (Compare And Set)
@ ๋ฌธ์ 5: ์ฝ๋ ๋์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ2 (phantom read)
์ฒ์ ์กฐํ์๋ ์๋ ๋ฐ์ดํฐ๊ฐ ์๊ธฐ๋ ๊ฒฝ์ฐ. (๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋๊ฑด ์๋, ๋ฌผ๋ฆฌ์ ์ธ ๊ฒฝ์์ํ X)
๋ฌธ์ 5 ํด๊ฒฐ์ฑ
- Serializable : ๋ชจ๋ ํธ๋์ญ์ ์ ์์๋๋ก ์คํ (๊ฒน์น์ง ์์)
- ๋ค๋ง ์ฑ๋ฅ์ด ๋๋ฌด ๊ตฌ๋ ค์ ์์ ์์๋๋ก๋ ์ฌ์ฉํ๋๊ฑด ์๋๊ณ ์ธ๋ฑ์ค ๋จ์ ์ ๊ธ์ด๋ ํน์ ์กฐ๊ฑด๊ธฐ๋ฐ ์ ๊ธ์ ์ฌ์ฉ
# JDBC ํธ๋์ญ์ ๊ณผ Connection
JDBC ํธ๋์ญ์ ์ ํ๋์ Connection์ ๊ฐ์ ธ์ ์ฌ์ฉํ๋ค๊ฐ ๋ซ๋ ์ฌ์ด์ ์ผ์ด๋๋ค. ์ฆ ํ ํธ๋์ญ์ ์ ์์๊ณผ ์ข ๋ฃ๋ ํ ์ปค๋ฅ์ ๊ฐ์ฒด์ ์ํด ์ด๋ฃจ์ด์ง๋ค. ์ด๋ ๊ฒ ํ๋์ DB์ปค๋ฅ์ ์์ ๋ง๋ค์ด์ง๋ ํธ๋์ญ์ ์ ๋ก์ปฌ ํธ๋์ญ์ ์ด๋ผ ํ๋ค. 2๊ฐ์ด์์ DB์์ ๋ฐ์ํ๋ ํธ๋์ญ์ ์ Commit์ ํ๋๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌํ๋๊ฑธ ๊ธ๋ก๋ฒ ํธ๋์ญ์ ์ด๋ผ๊ณ ํ๋ค. ์์์ ์ธ๊ธํ์๋ค.
๊ทธ๋ฐ๋ฐ ์ฑ๋ฅ์ ์ฌ๋ฆฌ๊ธฐ์ํด ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ํ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ด์ ์ฒ๋ฆฌํ ์ ์์๊น? ๊ทธ๋ฌ๋๊น, user๋ง๋ค ์ปค๋ฅ์ ์ ์์ฑํ๋๊ฒ ์๋๋ผ ์๋น์ค(UserSerivce)์์ ์ปค๋ฅ์ ์ ๊ณตํต์ผ๋ก ๋๋ ค ์ฌ์ฉํ๋๊ฑฐ์ง.
- Connection ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ง๋ง๊ณ ๋๋ ค์ธ๊น? ์ฌ๋ฌ ํธ๋์ญ์ ํ ์ปค๋ฅ์ ์ข์ง์๋?
- ๊ทธ๋ฌ๋ฉด ์ฝ๋๊ฐ ๋๋ฌด ๋๋ฌ์์ง์ง์๋? DAO๋ฅผ ๋ถ๋ฆฌํ ์ด์ ๊ฐ๋ญ์ง?
- ํ ์คํธ๋ ์ด๋ป๊ฒ ๋๋ฆฌ๋ผ๊ณ ;;
# ํธ๋์ญ์ ๊ฒฝ๊ณ์ค์
ํธ๋์ญ์ ์ด ์์๋๊ณ ๋๋๋ ์์น(๊ฒฝ๊ณ)๋ฅผ ๋ฐ๊พธ๋ฉด ๋๋ค. ํ ํธ๋์ญ์ ์ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ๋ฃ์ผ๋ฉด ๋๋ค๋๋ง
Connection c = dataSource.getConnection();
c.setAutoCommit(false); // ํธ๋์ญ์
๊ฒฝ๊ณ ์์ (์๋ ๊ฒฝ๊ณ ์ทจ์)
try {
PreparedStatement st1 =
c.prepareStatement("update users ...");
st1.executeUpdate();
PreparedStatement st2 =
c.prepareStatement("delete users ...");
st2.executeUpdate();
c.commit(); // ํธ๋์ญ์
๊ฒฝ๊ณ ๋์ง์ (์ปค๋ฐ)
} catch(Exception e) {
c.rollback(); // ํธ๋์ญ์
๊ฒฝ๊ณ ๋์ง์ (๋กค๋ฐฑ)
}
c.close();
# ๋น์ฆ๋์ค ๋ก์ง(์๋น์ค) ๋ด์ ํธ๋์ญ์ ๊ฒฝ๊ณ ์ค์ ๋ฃ๊ธฐ
์ด์ฌํ ๋น์ฆ๋์ค ๊ฐ์ฒด์ DAO ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํด๋จ๋๋, ๋น์ฆ๋์ค ๋ก์ง์์ ํธ๋์ญ์ ์ ๋ค์ ๋ค๋ค์ผํ๋ค. ๋ฌผ๋ก ๋ฌด์ง์ฑ์ผ๋ก SuperDaoWithService ์ด๋ฐ ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ๋ ์๊ฒ ์ง๋ง.. ํ์ค์ ์ผ๋ก ๋ง์ด ์๋๋ค. ์ฐจ๋ผ๋ฆฌ UserService ๋ด๋ถ์์ Connection ๊ฐ์ฒด์ ํธ๋์ญ์ ๊ฒฝ๊ณ์ค์ ์ ์ํ ์ต์ํ์ ์ฝ๋๋ง ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ ์ด์ฉํด๋ณด๋๋ก ํ์.
// UserService ๊ฐ์ฒด
public void upgradeLevels() throws Exception {
// (1) DB Connection ์์ฑ
// (2) ํธ๋์ญ์
์์
try {
// (3-1) DAO ๋ฉ์๋ ํธ์ถ add(Connection c, User user);
// (3-2) DAO ๋ฉ์๋ ํธ์ถ get(Connection c, String id);
// (3-3) DAO ๋ฉ์๋ ํธ์ถ update(Connection c, User user);
// (4) ํธ๋์ญ์
์ปค๋ฐ
}
catch(Exception e) {
// (5) ํธ๋์ญ์
๋กค๋ฐฑ
throw e;
}
finally {
// (6) DB Connection ์ข
๋ฃ
}
}
์์์ ๋งํ์ง๋ง ์ฐ๋ฆฌ๋ SuperDaoWithService๋ฅผ ๋ง๋ค๊ฒ ์๋๋ผ์ ํธ๋์ญ์ ๊ฒฝ๊ณ์ค์ (commit, rollback)๋ง ํ ๋ค์์ UserDao๋ก ์ปค๋ฅ์ ๊ด๋ฆฌ๋ฅผ ๋๊ธฐ๋ ์ฝ๋๋ฅผ ์์ฑํ ๊ฒ์ด๋ค.
// UserService์์ ํธ๋์ญ์
๊ฒฝ๊ณ์ค์ ์ ํ ๋ค, ํด๋น ์ปค๋ฅ์
์ UserDao๋ก ๋๊น
public interface UserDao {
public void add(Connection c, User user);
public User get(Connection c, String id);
...
public void update(Connection c, User user);
}
@ ์ด๋ ๊ฒ ํ์ ๋ ๋ฌธ์ ์
- DB์ปค๋ฅ์
์ ๋น๋กฏํ JdbcTemplate์ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค. ๊ฒฐ๊ตญ JDBC API๋ฅผ ์ง์ ์ฌ์ฉํ๋ ์ด๊ธฐ ๋ฐฉ์์ผ๋ก ๋์๊ฐ์ผ ํ๋ค. try/catch/finally ๋ธ๋ก์ ์ด์ UserService ๋ด์ ์กด์ฌํ๋ค.
- UserService์ ๋ฉ์๋์ Connection ํ๋ผ๋ฉํ ์ถ๊ฐ๋ผ์ผ ํ๋ค๋ ์ ์ด๋ค. upgardeLevels()์์ ์ฌ์ฉํ๋ ๋ฉ์๋์ ์ด๋๊ฐ์์ DAO๋ฅผ ํ์๋ก ํ๋ค๋ฉด, ๊ทธ ์ฌ์ด์ ๋ชจ๋ ๋ฉ์๋์ ๊ฑธ์ณ์ Connection ๊ฐ์ฒด๊ฐ ์ ๋ฌ๋๋ค.
- ์ฌ์ง์ด ์คํ๋ง์์๋ UserService๋ ์ฑ๊ธํค ๋น์ผ๋ก ๋์ด ์์ผ๋ ์ํ๊ฐ ์ด์ฉํ ์๋ ์๋ค. ์ฆ ๊ฐ์ฒด ํ๋์ Connection์ ์ ์ฅํด๋๋ค๊ฐ ๋ค๋ฅธ ๋ฉ์๋์์ ๋๋ ค์ฐ๊ฒ ํ ์ ์๋ค. ๊ฒฐ๊ตญ ํธ๋์ญ์
์ด ํ์ํ ์์
์ ์ฐธ์ฌํ๋ UserService์ ๋ฉ์๋๋ Connection ํ๋ผ๋ฏธํฐ๋ก ์ง์ ๋ถํด์ง ๊ฒ์ด๋ค.
- UserDao๋ ๋์ด์ ๋ฐ์ดํฐ ์์ธ์ค ๊ธฐ์ ์ ๋
๋ฆฝ์ ์ด์ง ์๋ค. JPA๋ ํ์ด๋ฒ๋ค์ดํธ๋ก UserDao์ ๊ตฌํ ๋ฐฉ์์ ๋ณ๊ฒฝํ๋ ค๊ณ UserService ์ฝ๋๋ ํจ๊ป ์์ ๋ผ์ผ ํ๋ค. ๊ธฐ๊ป ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํด DAO๋ฅผ ๋ถ๋ฆฌํ๊ณ DI๋ฅผ ์ ์ฉํ๋ ์๊ณ ๊ฐ ๋ฌผ๊ฑฐํ์ด ๋๊ณ ๋ง ๊ฒ์ด๋ค.
- DAO ๋ฉ์๋์ Connection ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๊ฒ ํ๋ฉด ํ ์คํธ์ฝ๋์๋ ์ํฅ์ ๋ฏธ์น๋ค. ์ง๊ธ๊น์ง DB ์ปค๋ฅ์ ์ ์ ํ ์ ๊ฒฝ์ฐ์ง ์๊ณ ํ ์คํธ์์ UserDao๋ฅผ ์ฌ์ฉํ ์ ์์๋๋ฐ, ์ด์ ๋ ํ ์คํธ ์ฝ๋์์ ์ง์ Connection ์ค๋ธ์ ํธ๋ฅผ ์ผ์ผ์ด ๋ง๋ค์ด์ DAO ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ก ๋ชจ๋ ๋ณ๊ฒฝํด์ผ ํ๋ค.
# ํด๊ฒฐ์ฑ : ํธ๋์ญ์ ๋๊ธฐํ
์ด๋ฏธ ์๊ณ ์๊ฒ ์ง๋ง, ์คํ๋ง์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฉ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
์์์ ํธ๋์ญ์ ๊ฒฝ๊ณ๋ฅผ ์ง์ ํด์คฌ์ ๋ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์, Service๊ฐ์ฒด์์ ์ปค๋ฅ์ ์ ๊ด๋ฆฌํ๋ค๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์คํ๋ง์ด ์ ์ํ๋ ๋ฐฉ๋ฒ์, ๋ ๋ฆฝ์ ์ธ ํธ๋์ญ์ ๋๊ธฐํ(Transaction Sychronization) ๋ฐฉ์์ด๋ค.
@ ํธ๋์ญ์ ๋๊ธฐํ๋
ํธ๋์ญ์ ์ ์์ํ๊ธฐ์ํด ๋ง๋ Connection ๊ฐ์ฒด๋ฅผ ํน๋ณํ ์ฅ์์ ๋ณด๊ดํด๋๊ณ , ์ดํ DAO ๋ฉ์๋์์ ๊ฐ์ ธ๋ค๊ฐ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ค. ์ด ๋, ๋๊ธฐํ ์ ์ฅ์(TransactionSync)์์ ์ด๋ฏธ ์ฌ์ฉํ๊ณ ์๋ ํธ๋์ญ์ ์ ์ปค๋ฅ์ ์ด ์๋ค๋ฉด ์ฌ์ฌ์ฉํ๋ค. ์ด๋ฅผ ํธ๋์ญ์ ๋๊ธฐํ ๋ฐฉ์์ด๋ผ๊ณ ๋งํ๋ค. ํธ๋์ญ์ ๋๊ธฐํ ์ ์ฅ์(TransactionSync)๋ ์์ ์ค๋ ๋๋ง๋ค ๋ ๋ฆฝ์ ์ผ๋ก ๋ถ๋ฆฌํ์ฌ Connection์ ์ ์ฅ, ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์ถฉ๋๋ ์ผ๋ ค๋ ์๋ค.
- UserService๊ฐ ์ปค๋ฅ์ ์์ฑ -> TransactionSync์ ์ ์ฅ -> ํธ๋์ญ์ ๊ฒฝ๊ณ์ค์ setAutoCommit(false)
- UserDao.update๋ ์ปค๋ฅ์ ์ ๋ฐ์์์ ์ฌ์ฉ (์ด๋ฏธ ์ฌ์ฉํ๊ณ ์๋ ํธ๋์ญ์ ์ด ์๋ค๋ฉด ๋๊ธฐํํด์ ํจ๊ป ์ฌ์ฉ)
- ์ปค๋ฅ์ ์ ๋ซ์ง์์ ์ํ๋ก ์์ ์ ๋ง์น๊ณ , TransactionSycn์ ๋ค์ ์ปค๋ฅ์ ์ ์ฅ.
@ ์คํ๋ง ํธ๋์ญ์ ๋๊ธฐํ ์ ์ฉ
์์ด๋์ด๋ ๊ธ๋ก๋ฒํ ๊ณต๊ฐ์ ํธ๋์ญ์ ์ ์ ์ ์ ์ฅํด๋๋ค๋ ๊ฒ์ผ๋ก ๊ฐ๋จํ์ง๋ง, ์ง์ ๊ตฌํํ๋ ๊ฑด ๊ธฐ์ ์ ์ผ๋ก ์ ๋ ์ฝ์ง ์๋ค. ๊ทธ๋์ ์คํ๋ง์ ์๋์ ๊ฐ์ ํธ๋์ญ์ ๋๊ธฐํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
- ํธ๋์ญ์ ๋๊ธฐํ ๊ด๋ฆฌ(TransactionSynchronizationManager)๋ฅผ ์ด์ฉ
- ์ปค๋ฅ์
์ ๊ฐ์ ธ์ฌ ๋๋ ๋ฐ๋ฉํ ๋ DataSourceUtils๋ผ๋ ์คํ๋ง ์ ๊ณต ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉ
=> ๋๊ธฐํ ๊ฐ๋ฅํ ํธ๋์ญ์ ์ด ์๋ค๋ฉด ๊ฐ์ ์ปค๋ฅ์ ์ ์ฌ์ฉ. ์๋ค๋ฉด ์๋ก์ด ์ปค๋ฅ์ ์ ์์ฑ
public void upgradeLevels() throws SQLException{
// ํธ๋์ญ์
๋๊ธฐํ ๊ด๋ฆฌ์๋ฅผ ์ด์ฉํด ๋๊ธฐํ ์์
์ ์ด๊ธฐํ
TransactionSynchronizationManager.initSynchronization();
// DB ์ปค๋ฅ์
์ ์์ฑํ๊ณ ํธ๋์ญ์
์ ์์ํ๋ค.
// ์ดํ์ DAO ์์
์ ๋ชจ๋ ์ฌ๊ธฐ์ ์์ํ ํธ๋์ญ์
์์์ ์งํ๋๋ค.
// ์๋ ๋ ์ค์ด DB ์ปค๋ฅ์
์์ฑ๊ณผ ๋๊ธฐํ๋ฅผ ํจ๊ป ํด์ค๋ค.
Connection c = DataSourceUtils.getConnection(dataSource);
c.setAutoCommit(false);
try {
List<User> users = userDao.getAll();
for (User user : users) {
if (canUpgradeLevel(user)) {
upgradeLevel(user);
}
}
c.commit();
}catch(Exception e) {
c.rollback();
throw e;
} finally {
// ์คํ๋ง DataSourceUtils ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ฅผ ํตํด ์ปค๋ฅ์
์ ์์ ํ๊ฒ ๋ซ๋๋ค.
DataSourceUtils.releaseConnection(c, dataSource);
// ๋๊ธฐํ ์์
์ข
๋ฃ ๋ฐ ์ ๋ฆฌ
TransactionSynchronizationManager.unbindResource(this.dataSource);
TransactionSynchronizationManager.clearSynchronization();
}
}
# ํ๊ฑธ์ ๋, ํธ๋์ญ์ ์๋น์ค ์ถ์ํ
ํธ๋์ญ์ ๋๊ธฐํ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ๋ค, ๊ฒฐ๊ตญ Connection์ Service ๊ฐ์ฒด๊ฐ ๋ค๋ค์ผํ๋๊ฑด ๋ณํจ์๋ค. ์ฆ DB์ ๊ทผ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋น์ค ์์ญ์์ ์ฝ๋๋ณ๊ฒฝ์ด ํ์ํ๋ค๋ ๋ง์ด๋ค. ๋ค์ ์ฒ์์ผ๋ก ๋์๊ฐ๋ณด์. ์ฐ๋ฆฌ๊ฐ ์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋์ง๋ฅผ.
@ ์คํ๋ง์ ํธ๋์ญ์ ์๋น์ค ์ถ์ํ
์คํ๋ง์ ํธ๋์ญ์ ๊ธฐ์ ์ ๊ณตํต์ ์ ๋ด์ ํธ๋์ญ์ ์ถ์ํ ๊ธฐ์ ์ ์ ๊ณตํ๋ค. ์ด๋ฅผ ์ด์ฉํ๋ฉด ํน์ ๊ธฐ์ ์ ์ข ์๋์ง ์๊ณ ํธ๋์ญ์ ๊ฒฝ๊ณ ์ค์ ์์ ์ด ๊ฐ๋ฅํด์ง๋ค.
UserService๋ ํธ๋์ญ์ ๋งค๋์ ์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ ๋ฟ, ๋ ์ด์ DAO ๊ฐ์ฒด์ ์์กดํ์ง ์๋๋ค.
- ์ดํด๋ฅผ ๋๊ธฐ์ํด PlatformTransactionManger๋ฅผ ์ง์ ์ ์ฉ์์ผ๋ณด์
TransactionStatus ๊ฐ์ฒด
public interface TransactionStatus extends SavepointManager {
boolean isCompleted();
boolean isNewTransaction();
boolean hasSavepoint();
boolean isRollbackOnly();
void setRollbackOnly();
void flush();
}
public class UserService {
@Autowired UserService userService;
// ํธ๋์ญ์
๋งค๋์ ์ ๊ตฌํ์ฒด๋ ์ ๋์ ์ผ๋ก ๋ฐ๋ ์ ์๋ค. JDBC์๊ฒฝ์ฐ DataSourceTxManager
@Autowired PlatformTransactionManager transactionManager;
//ํธ๋์ญ์
๊ฒฝ๊ณ์ค์ ์ฝ๋
public void insertUserTest() {
TransactionStatus status= //ํธ๋์ญ์
์ ์์์ ์๋ฆฐ๋ค.(ํธ๋์ญ์
์ ์ป์ด์ค๋ ์์ ์ด ์์)
this.transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
List<User> users = userDao.getAll();
for (User user : users) {
if (canUpgradeLevel(user)) {
upgradeLevel(user);
}
}
transactionManager.commit(status);
}catch(Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
์ฆ DB์ ๊ทผ ๊ธฐ์ ์ด JTA๋ Hibernate๋ฑ์ผ๋ก ๋ณ๊ฒฝ๋๋ค๊ณ ํด๋ UserService๋ ํธ๋์ญ์ ๋งค๋์ ์ธํฐํ์ด์ค๋ง ์์กดํ๊ณ ์๊ธฐ๋๋ฌธ์ ๋ณ๊ฒฝํ ํ์๊ฐ ์์ด์ง๋ค. ๋จ์ง PlatformTransactionManger ์ธํฐํ์ด์ค์ ์ฃผ์ ํ๋ ๋น๋ง ๋ณ๊ฒฝํ๋ฉด ๋๋ค.
'๐ฑ Spring Framework > Spring Core' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์๋ฐ AOP์ ๋ชจ๋ ๊ฒ(Spring AOP & AspectJ) (3) | 2022.03.09 |
---|---|
DB์ @Transactional์ ์ฌ์ฉํ ๋ ์์ฃผ ๋์ค๋ ์ค์ (0) | 2021.08.18 |
@Transactional ์ ๋์์๋ฆฌ, ํธ๋์ญ์ ๋งค๋์ (5) | 2021.08.18 |
์ฝ๊ฒ ์ดํดํ๋ ์คํ๋ง AOP (~์์ฑ์ค~) (0) | 2021.08.18 |
ํ ๋น์์คํ๋ง#2 ์ฑ๊ธํค ๋ ์ง์คํธ๋ฆฌ์ ์ค๋ธ์ ํธ ์ค์ฝํ (0) | 2021.08.14 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev