ํธ๋์ญ์ ์ธํฐํ์ด์ค, ํธ๋์ญ์ ํ ํ๋ฆฟ์ ์ด์ฉํ Service ๊ณ์ธต์ Transaction ๋ฌธ์ ํด๊ฒฐ
by rlaehddnd0422์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ
์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ ์ค ๊ฐ์ฅ ๋จ์ํ๋ฉด์ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ญํ ์ ๋ฐ๋ผ 3๊ฐ์ง ๊ณ์ธต์ผ๋ก ๋๋๋ ๋ฐฉ๋ฒ์ ๋๋ค.
์ปจํธ๋กค๋ฌ ๊ณ์ธต
- ์น ์์ฒญ(request), ์๋ต(response)๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฌ์ฉ์ ์์ฒญ์ ๊ฒ์ฆํ๋ ์ญํ
- ํด๋ผ์ด์ธํธ๊ฐ ์ ๊ทผํ๋ UI ๊ด๋ จ๋ ๊ธฐ์ ์ธ ์น, ์๋ธ๋ฆฟ, HTTP์ ๊ด๋ จ๋ ๋ถ๋ถ์ ๋ด๋น
- ์ฃผ๋ก Servlety๊ณผ HTTP ๊ฐ์ ์น ๊ธฐ์ ์ ์ฌ์ฉํ๊ณ MVC(Model + View + Controller)๊ตฌ์กฐ๋ฅผ ์ด๋ฃจ๊ณ ์์ต๋๋ค.
์๋น์ค ๊ณ์ธต
- ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ ๊ณ์ธต์ ๋๋ค.
- ํน์ ๊ธฐ์ ์ ์์กดํ์ง ์๊ณ ์์ ์๋ฐ์ฝ๋๋ก ์์ฑ
๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต
- ์ค์ DB์ ์ ๊ทผํ๋ ์ฝ๋๊ฐ ์์ฑ๋ ๊ณ์ธต
- ์ฃผ๋ก JDBC, JPA ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ ๊ณ์ธต์ ์๋น์ค ๊ณ์ธต์ ๋๋ค. ์๋น์ค ๊ณ์ธต์ ์ปจํธ๋กค๋ฌ ๊ณ์ธต๊ณผ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์,ํน์ ๊ตฌํ ๊ธฐ์ ์ ์ง์ ์์กดํ๊ฒ ๋๋ฉด ๋์ค์ ๊ตฌํ ๊ธฐ์ ์ด ๋ณ๊ฒฝ๋ ๋ ์ํฅ์ ๋ฐ๊ธฐ ๋๋ฌธ์ ๊ฐ๊ธ์ ๋น์ฆ๋์ค ๋ก์ง๋ง ๊ตฌํํ๊ณ ์ต๋ํ ์ข ์๋ฐ์ง ์๊ฒ ์์ํ๊ฒ ์ ์ง๋์ด์ผ ํฉ๋๋ค.
์๋น์ค ๊ณ์ธต์ ์์ํ๊ฒ ์ ์งํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น์?
์ด ์ ํฌ์คํ ์์ ์คํ๋ง์ ์ฌ์ฉํ์ง ์๊ณ ํธ๋์ญ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด๋ณด์์์ต๋๋ค. ์ ๊น ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด
@Slf4j
@RequiredArgsConstructor
public class MemberServiceV2 {
private final MemberRepositoryV2 memberRepository;
private final DataSource dataSource;
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
Connection con = dataSource.getConnection();
try
{
con.setAutoCommit(false); // ํธ๋์ญ์
์์
buisnesslogic(con, fromId, toId, money);
con.commit();
} catch (Exception e) {
log.error("error detected!");
con.rollback();
throw new IllegalStateException(e);
} finally {
release(con);
}
}
- ์๋น์ค ๊ณ์ธต์ ๊ณ์ข์ด์ฒด ๋ก์ง์ ๋ณด๋ฉด ํธ๋์ญ์ ์ ์์ํ๊ณ , ๋น์ฆ๋์ค ๋ก์ง์ ์ํํ๊ณ , ๋น์ฆ๋์ค ๋ก์ง์ค ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋กค๋ฐฑํ๊ณ , ์ต์ข ์ ์ผ๋ก connection์ ๋ฐ๋ฉํ๋ ์์ ๊น์ง ๋ชจ๋ ํ ๋ก์ง(๋ฉ์๋)์์ ๊ตฌํ๋์์ต๋๋ค.
- ์ถ๊ฐ์ ์ผ๋ก ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์ผ๋ก๋ถํฐ ์ฌ๋ผ์ค๋ SQLException ๋ํ JDBC ๊ธฐ์ ์ ์์กดํฉ๋๋ค.
- ์ด๋ ๊ฒ ์๋น์ค ๊ณ์ธต์์ ์์ํ๊ฒ ๋น์ฆ๋์ค ๋ก์ง๋ง ์ํํด์ผ ํ๋๋ฐ ๊ทธ๋ ์ง ๋ชปํ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ํธ๋์ญ์ ์ ํ๊ธฐ ์ํด JDBC ๊ธฐ์ (DataSource๋ฅผ ํตํ ์ปค๋ฅ์ ํ๋)์ ์ฌ์ฉํ๊ณ ์์ด์.
- ์ด๋ ๊ฒ ๋๋ฉด ๋ง์ฝ JDBC ๊ธฐ์ ์์ JPA ๊ฐ์ด ๋ค๋ฅธ ๊ธฐ์ ๋ก ๋ณ๊ฒฝํ๊ฒ ๋๋ฉด ์ ์ฒด์ ์ธ ์๋น์ค ๊ณ์ธต์ ์ฝ๋๋ฅผ ์์ ํด์ผ ํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ ๋ฆฌํ๋ฉด ์๋น์ค ๊ณ์ธต์์ ์ด 3๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
1. ํธ๋์ญ์ ๋ฌธ์ : JDBC ๊ตฌํ ๊ธฐ์ ์ด ์๋น์ค ๊ณ์ธต์ ๊ตฌํ, ๊ฐ์ ํธ๋์ญ์ ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ปค๋ฅ์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ ๋ฉ์๋๋ฅผ ๋ง๋ฆ์ผ๋ก์จ ๋ฐ์ํ๋ ์ค๋ฒ๋ก๋ฉ
2. JDBC ๋ฐ๋ณต ๋ฌธ์ : try-catch-finally ์ ์ปค๋ฅ์ ์ ๋ฐ๊ณ pstmt ์ฌ์ฉํด์ ๊ฒฐ๊ณผ๋ฅผ ๋งคํ, ์คํ์ ๋ฐ๋ณต ..
2. ์์ธ ๋์ ๋ฌธ์ : Repository ๊ณ์ธต์ผ๋ก๋ถํฐ ์ ํ๋ ์์ธ๊ฐ JDBC ๊ธฐ์ ์ ์์กดํ๋ ๋ฌธ์
์ด๋ฐ ๋ฌธ์ ๋ค์ ์คํ๋ง์ ์ฌ์ฉํด์ ์๋น์ค ๊ณ์ธต์ ์์ํ๊ฒ ์ ์งํ๋ฉด์ ์์ ๊ธฐ์ ํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ ์ ์์ต๋๋ค.
Sol 1. ํธ๋์ญ์ ์ถ์ํ - (Service ๊ณ์ธต TransactionManager) + (Repository ๊ณ์ธต Transaction Synchronize Manager)
ํ์ฌ ์๋น์ค ๊ณ์ธต์์๋ ํธ๋์ญ์ ์ ํ๊ธฐ ์ํด JDBC ๊ธฐ์ ์ ์์กดํ๊ณ ์์ต๋๋ค.
์์ ๋ค๋ฅธ ๋ฐ์ดํฐ ์ ๊ทผ ๊ธฐ์ ์ธ JPA๋ก ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ์๋น์ค ๊ณ์ธต์ ํธ๋์ญ์ ๊ด๋ จ ์ฝ๋๋ ๋ชจ๋ ํจ๊ป ์์ ํด์ผ ํฉ๋๋ค.
(JDBC์ con.setAutoCommit(false)์ผ๋ก ํธ๋์ญ์ ์ ์์ํ์ง๋ง, JPA๋ transaction.begin()์ ํตํด ํธ๋์ญ์ ์ ์์)
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ํธ๋์ญ์ ๊ธฐ๋ฅ์ ์ถ์ํ ํ๋ฉด ๋ฉ๋๋ค.
์คํ๋ง์ ํธ๋์ญ์ ์ถ์ํ ๊ธฐ์ ์ ์ด๋ฏธ ์ ๊ณตํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด ๊ธฐ์ ์ ์ฌ์ฉํด ์๋น์ค ๊ณ์ธต์์ ์ถ์ํ์ ์์กดํ๋ฉด ๋ฉ๋๋ค.
์คํ๋ง์ด ์ ๊ณตํ๋ ํธ๋์ญ์ ์ถ์ํ ๊ธฐ์ ์ ์ธํฐํ์ด์ค๋ PlatformTransactionManager์ ๋๋ค.
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
- getTransaction() : ํธ๋์ญ์ ์ ์์
- commit() : ํธ๋์ญ์ ์ ์ปค๋ฐ
- rollback() : ํธ๋์ญ์ ์ ๋กค๋ฐฑ
์ด์ ์ถ์ํ๋ฅผ ์ฌ์ฉํด ์ด์ DataSource๋ฅผ ์์กดํ์ง ์๊ณ ์๋น์ค ๊ณ์ธต์์ PlatformTransactionManager ์ธํฐํ์ด์ค์ ์์กด(์ธ๋ถ์์ ๊ตฌํ์ฒด ์ฃผ์ )ํด์ ํธ๋์ญ์ ์ ์์ฑ, ์ปค๋ฐ, ๋กค๋ฐฑํ ์ ์์ต๋๋ค. ์๋น์ค ๊ณ์ธต์ PlatformTranscationManager๋ฅผ ์ค์ฌ์ ํธ๋์ญ์ ๋งค๋์ ๋ผ๊ณ ์นญํฉ๋๋ค.
์ถ๊ฐ๋ก ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์์ ํธ๋์ญ์ ๋งค๋์ ๋ฅผ ํตํด ์์ฑ๋ ์ปค๋ฅ์ ์ ์ฌ์ฉํ๋ ค๋ฉด ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋จํฉ๋๋ค. ํธ๋์ญ์ ๋งค๋์ ์ ๋ณด๊ด๋์ด ์๋ ์ปค๋ฅ์ ์ ๋ฐ์์ฌ ๋ DataSourceUtils์ getConnection()์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
// ํธ๋์ญ์
๋๊ธฐํ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด DataSourceUtils๋ฅผ ํตํด ์ปค๋ฅ์
์ป์ด์ผํจ.
Connection con = DataSourceUtils.getConnection(dataSource);
ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋ ์ฐ๋ ๋ ๋ก์ปฌ์ด๋ผ๋ ๊ธฐ์ ์ ์ฌ์ฉํด ์ปค๋ฅ์ ์ ๋๊ธฐํ ํด์ค๋๋ค. ์ฐ๋ ๋ ๋ก์ปฌ์ ๋ฉํฐ ์ฐ๋ ๋ ์ํฉ์ ์์ ํ๊ฒ ์ปค๋ฅ์ ์ ๋๊ธฐํ ํด์ฃผ๊ธฐ ๋๋ฌธ์, ์๋น์ค ๊ณ์ธต์์ ์์ฑํ ์ปค๋ฅ์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์ ๋๊ฒจ์ค ํ์๊ฐ ์์ต๋๋ค!
์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์๋น์ค ๊ณ์ธต๊ณผ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์ ์ฝ๋๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Service ๊ณ์ธต
@Slf4j
@RequiredArgsConstructor
public class MemberServiceV3_1 {
private final PlatformTransactionManager transactionManager;
private final MemberRepositoryV3 memberRepository;
public void accountTransfer(String fromId, String toId, int money) throws SQLException
{
// ํธ๋์ญ์
์์
// ์ปค๋ฅ์
์์ฑ
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try
{
buisnesslogic(fromId, toId, money);
transactionManager.commit(status);
} catch (Exception e) {
log.error("error detected!");
transactionManager.rollback(status);
throw new IllegalStateException(e);
} // release๋ transactionManager๊ฐ ์์์ ํด์ค.
}
ํธ๋์ญ์ ๋งค๋์ ๊ฐ dataSource๋ฅผ ํตํด ์ปค๋ฅ์ ์ ์์ฑํด์ฃผ๋ ๋๋ถ์ ์ด์ ์๋น์ค ๊ณ์ธต์์๋ dataSource๋ฅผ ์์กดํ ํ์๊ฐ ์์ต๋๋ค.
ํธ๋์ญ์ ๋งค๋์ ์ ๊ตฌํ์ฒด๋ JDBC ๊ธฐ์ ์ ์ฌ์ฉํ๋ฏ๋ก DataSourceTransactionManager ๊ตฌํ์ฒด๋ฅผ ์ธ๋ถ์์ ์ฃผ์ ํฉ๋๋ค.
(dataSource๋ํ JDBC ๊ธฐ์ ์ DriverManagerDataSource ๊ตฌํ์ฒด๋ฅผ ์ธ๋ถ์์ ์ฃผ์ ํฉ๋๋ค)
- transactionManager๋ getTransaction()์ ํตํด ํธ๋์ญ์
์ ์์ฑํ๊ณ , status๋ฅผ ๋ฆฌํดํฉ๋๋ค. status์๋ ํ์ฌ ํธ๋์ญ์
์ ์ํ๊ฐ ํฌํจ๋์ด ์์ด, ์ปค๋ฐ, ๋กค๋ฐฑ์์ ํ์ํฉ๋๋ค.
- getTransaction ๋ด๋ถ ํ๋ผ๋ฏธํฐ์ ํธ๋์ญ์ ๊ด๋ จ ์ต์ ์ ์ง์ ๊ฐ๋ฅ. ์ฌ๊ธฐ์๋ Default์ธ DefaultTransactionDefinition ๊ฐ์ฒด๋ฅผ ์ฌ์ฉ
- transactionManager.commit(status) : ํธ๋์ญ์ ์ปค๋ฐ
-
transactionManager.rollback(status) : ํธ๋์ญ์ ๋กค๋ฐฑ
Repository ๊ณ์ธต
@Slf4j
@RequiredArgsConstructor
public class MemberRepositoryV3 {
private final DataSource dataSource;
private Connection getConnection() throws SQLException {
// ํธ๋์ญ์
๋๊ธฐํ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด DataSourceUtils๋ฅผ ํตํด ์ปค๋ฅ์
์ป์ด์ผํจ.
Connection con = DataSourceUtils.getConnection(dataSource);
log.info("get connection = {}, class = {}",con,con.getClass());
return con;
}
private void close(Connection con, Statement stmt, ResultSet rs)
{
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(stmt);
// ํธ๋์ญ์
๋๊ธฐํ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด DataSourceUtils ์ฌ์ฉํด์ผ ํจ.
// ํธ๋์ญ์
์ ์ฌ์ฉํ๊ธฐ ์ํด ๋๊ธฐํ๋ ์ปค๋ฅ์
์ ๋ซ์ง ์๊ณ ์ ์ง.
// ํธ๋์ญ์
๋๊ธฐํ ๋งค๋์ ๊ฐ ๊ด๋ฆฌํ๋ ์ปค๋ฅ์
์ด ์๋ ๊ฒฝ์ฐ์ ํด๋น ์ปค๋ฅ์
๋ซ์.
DataSourceUtils.releaseConnection(con,dataSource);
}
- ํธ๋์ญ์ ๋งค๋์ ๋ฅผ ํตํด ์์ฑ๋ ์ปค๋ฅ์ ์ ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ์ ๋ณด๊ด๋ฉ๋๋ค!
- ๋๊ธฐํ ๋งค๋์ ์ ๋ณด๊ด๋ ์ปค๋ฅ์ ์ ์ฌ์ฉํ๊ธฐ ์ํด์ DataSourceUtils์ getConnection(dataSource)๋ฅผ ์ฌ์ฉํฉ๋๋ค. (dataSource๋ ์ธ๋ถ์์ DriverManagerDataSource ๊ตฌํ์ฒด๋ฅผ ์ฃผ์ ๋ฐ์ ์ฌ์ฉ)
- ์ปค๋ฐ์ด๋ ๋กค๋ฐฑ์ดํ ์ต์ข ์ ์ผ๋ก ์ปค๋ฅ์ ์ ๋ฐ๋์ DataSourceUtils์ releaseConnection ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ์ฒ๋ฆฌํด ์ฃผ์ด์ผ ํฉ๋๋ค. ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ธฐํ๋์ด ์๋ ์ปค๋ฅ์ ์ ๊ฒฝ์ฐ์๋ ์ปค๋ฅ์ ์ ๋ซ์ง์๊ณ ์ ์งํ๊ณ , ํธ๋์ญ์ ์ด ๋๋ ๊ฒฝ์ฐ(๋๊ธฐํ ๋งค๋์ ๊ฐ ๊ด๋ฆฌํ๋ ์ปค๋ฅ์ ์ด ์๋ ๊ฒฝ์ฐ)์๋ ์ปค๋ฅ์ ์ ๋ซ์์ค๋๋ค.
์ถ์ํํ ์ธํฐํ์ด์ค์ ๋ชจ๋ ๊ตฌํ์ฒด๋ ์ด ์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ธ๋ถ์์ ์ฃผ์ ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก ๊ทธ๋ฆผ์ ํตํด ์ ์ฒด์ ์ธ ๋์ํ๋ฆ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
1. ํธ๋์ญ์ ์์
1-1. ์๋น์ค ๊ณ์ธต์์ transactionManager.getTransaction()์ ํธ์ถํด ํธ๋์ญ์ ์์.
1-2. ํธ๋์ญ์ ๋งค๋์ ์์ datasource๋ฅผ ์ฌ์ฉํด ์ปค๋ฅ์ ์์ฑ.
1-3. ์ปค๋ฅ์ ์ ์๋ ์ปค๋ฐ ๋ชจ๋๋ก ๋ณ๊ฒฝํด์ ํธ๋์ญ์ ์ ์์.
1-4. ์ปค๋ฅ์ ์ ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ์ ๋ณด๊ด.
1-5. ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋ ์ฐ๋ ๋ ๋ก์ปฌ์ ์ปค๋ฅ์ ์ ๋ณด๊ด.
2. ๋น์ฆ๋์ค ๋ก์ง
2-1. ๋น์ฆ๋์ค ๋ก์ง์์ ๋ฐ์ดํฐ ์ ๊ทผ ๋ก์ง์ ํธ์ถ.
2-2. ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์์ ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ์์ ๋๊ธฐํ๋ ์ปค๋ฅ์ ์ ์กฐํ.
2-3. ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ์์ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์ ์ปค๋ฅ์ ์ ๋์ ธ์ค๋๋ค.
2-4. ์ปค๋ฅ์ ์ ๊ธฐ๋ฐ์ผ๋ก SQL๋ฌธ์ ์คํ.
3. ํธ๋์ญ์ ์ข ๋ฃ
3-1. ํธ๋์ญ์ ์ ์ปค๋ฐํ๊ฑฐ๋ ๋กค๋ฐฑํจ์ผ๋ก์จ ํธ๋์ญ์ ์ข ๋ฃ
3-2. ํธ๋์ญ์ ๋งค๋์ ์์ ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋ก๋ถํฐ ๋๊ธฐํ๋ ์ปค๋ฅ์ ์ ํ๋
3-3. ํ๋ํ ์ปค๋ฅ์ ์ ํตํด ํธ๋์ญ์ ์ ์ปค๋ฐ or ๋กค๋ฐฑํฉ๋๋ค
3-4. ์ ์ฒด ๋ฆฌ์์ค(ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ์ ์ฐ๋ ๋ ๋ก์ปฌ ์ ๋ฆฌ, con.setAutoCommit(true)๋ก ๋ณ๊ฒฝ, con.close() ํธ์ถ)๋ฅผ ์ ๋ฆฌํฉ๋๋ค.
์ ๋ฆฌํด๋ณด๋ฉด
- ํธ๋์ญ์ ์ถ์ํ ๋๋ถ์ ์ด์ JDBC ๊ธฐ์ ์ ์์กดํ์ง ์์ JDBC์์ JPA๋ก ๋ณ๊ฒฝํด๋ ์๋น์ค ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์ ์งํ ์ ์๊ฒ ๋์์ต๋๋ค. (๊ธฐ์ ๋ณ๊ฒฝ์ ์์กด๊ด๊ณ ์ฃผ์ ๋ง DataSourceTransactionManager์์ JpaTransactionManager๋ก ๋ณ๊ฒฝํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋จ)
- ํธ๋์ญ์ ๋๊ธฐํ ๋งค๋์ ๋๋ถ์ ์ปค๋ฅ์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ธฐ์ง ์์๋ ๋๊ฒ ๋์์ต๋๋ค.
- ์์ ๊ธฐ์ ํ๋ 1๋ฒ ํธ๋์ญ์ ๋ฌธ์ ๋ ํด๊ฒฐํ๋๋ฐ์. ์์ง 2๋ฒ JDBC ๋ฐ๋ณต ๋ฌธ์ ์ 3๋ฒ ์์ธ๋์ ๋ฌธ์ ๊ฐ ๋จ์์ต๋๋ค.
Sol2. ํธ๋์ญ์ ํ ํ๋ฆฟ ์ฌ์ฉ
Sol1์ ํธ๋์ญ์ ์ ์ฌ์ฉํ ์๋น์ค๊ณ์ธต ์ดํด๋ณด๋ฉด
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
// ํธ๋์ญ์
์์
// ์ปค๋ฅ์
์์ฑ
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try
{
buisnesslogic(fromId, toId, money);
transactionManager.commit(status);
} catch (Exception e) {
log.error("error detected!");
transactionManager.rollback(status);
throw new IllegalStateException(e);
} // release๋ transactionManager๊ฐ ์์์ ํด์ค.
}
try-catch-finally ํํ ๋ด์์ ํธ๋์ญ์ ์ ์์ํ๊ณ , ์ปค๋ฐ/๋กค๋ฐฑํ๋๋ฐ ์ด๋ฐ ํํ๊ฐ ์๋น์ค ๊ณ์ธต์์ ๋ฐ๋ณต๋์ง ์๊ฒ ์คํ๋ง์ด ์ง์ํ๋ ํ ํ๋ฆฟ ์ฝ๋ฐฑ ํจํด(TransactionTemplate)์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
ํธ๋์ญ์ ํ ํ๋ฆฟ ํด๋์ค
public class TransactionTemplate {
private PlatformTransactionManager transactionManager;
public <T> T execute(TransactionCallback<T> action){..}
void executeWithoutResult(Consumer<TransactionStatus> action){..}
}
- excute() : ์๋ต๊ฐ์ด ์์ ๋ ์ฌ์ฉ
- executeWithoutResult() : ์๋ต๊ฐ์ด ์์ ๋ ์ฌ์ฉ
์๋น์ค ๊ณ์ธต์์ ์ด ํ ํ๋ฆฟ ํด๋์ค๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
@Slf4j
public class MemberServiceV3_2 {
// private final PlatformTransactionManager transactionManager;
private final TransactionTemplate txTemplate;
private final MemberRepositoryV3 memberRepository;
public MemberServiceV3_2(PlatformTransactionManager transactionManager, MemberRepositoryV3 memberRepository)
{
this.txTemplate = new TransactionTemplate(transactionManager);
this.memberRepository = memberRepository;
}
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
// ํธ๋์ญ์
์์
// ์ปค๋ฅ์
์์ฑ
// TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
txTemplate.executeWithoutResult((status)-> {
try
{
buisnesslogic(fromId,toId,money);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
});
}
- TransactionTemplate์ ์ฌ์ฉํ๋ ค๋ฉด transactionManager๊ฐ ํ์ํฉ๋๋ค. ๋ฐ๋ผ์ ์์ฑ์์์ transactionManager๋ฅผ ์ฃผ์ ๋ฐ์ผ๋ฉด์ ํ ํ๋ฆฟ์ ์์ฑํ์ต๋๋ค.
- try-catch๋ฅผ ๋ณด๋ฉด ํธ๋์ญ์ ์ ์์ฑํ๊ณ , ์ปค๋ฐ/๋กค๋ฐฑํ๋ ๋ถ๋ถ๋ค์ด ํ ํ๋ฆฟ์ ํตํด ์คํํจ์ผ๋ก์จ ์ ๊ฑฐ๋์์ต๋๋ค.
- ํธ๋์ญ์
ํ
ํ๋ฆฟ์ ๊ธฐ๋ณธ๋์
- ๋น์ฆ๋์ค ๋ก์ง์ด ์ ์ ์ํ๋๋ฉด ์ปค๋ฐ.
- Uncheck ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋กค๋ฐฑ. check ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์ปค๋ฐ.
- ์ฝ๋์์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด try-catch๊ฐ ๋ค์ด๊ฐ๋๋ฐ ๋น์ฆ๋์ค๋ก์ง ์ํ์ค SQLException ์ฒดํฌ ์์ธ๋ฅผ ๋๊ฒจ์ฃผ๋๋ฐ, ํด๋น ๋๋ค์์ ์ฒดํฌ ์ฒดํฌ ์์ธ๋ฅผ ๋ฐ์ผ๋ก ๋์ง ์ ์๊ธฐ ๋๋ฌธ์ ์ธ์ฒดํฌ ์์ธ(IllegalStateException)๋ก ๋ฐ๊พธ์ด ๋์ง๋๋ก ์์ธ๋ฅผ ์ ํํ์ต๋๋ค.
<์ ๋ฆฌ>
- ํธ๋์ญ์ ํ ํ๋ฆฟ ๋๋ถ์ ์ปค๋ฐ, ๋กค๋ฐฑ ์์ ์ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์์์ต๋๋ค.
- ํ์ง๋ง ์ฌ์ ํ ์ด๊ณณ์ ์๋น์ค ๊ณ์ธต์ธ๋ฐ ๋น์ฆ๋์ค ๋ก์ง ๋ฟ๋ง ์๋๋ผ ํธ๋์ญ์ ์ ์ฒ๋ฆฌํ๋ ๊ธฐ์ ๋ก์ง์ด ํฌํจ๋์ด ์์ด ์์ํ ์๋น์ค ๊ณ์ธต์ด๋ผ๊ณ ๋ณด๊ธฐ ์ด๋ ต์ต๋๋ค.
- ์๋น์ค ๋ก์ง์๋ ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง๋ง ์์ด์ผ ํ์ง๋ง ํธ๋์ญ์ ๊ธฐ์ ์ ์ฌ์ฉํ๋ ค๋ฉด ์ด์ฉ ์ ์์ด ํธ๋์ญ์ ์ฝ๋๊ฐ ๋์์ผ ํ๋ ๋๋ ๋ง๊ฐ ์์ต๋๋ค.
- ๋ค์ ํฌ์คํ ์์ ํธ๋์ญ์ AOP๋ฅผ ์ฌ์ฉํด ํด๊ฒฐํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > DB Access' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํธ๋์ญ์ AOP + ์์ธ ์ ํ ์ ์ฉํ Service ๊ณ์ธต ๋ถ๋ฆฌ (0) | 2023.04.06 |
---|---|
Spring ํธ๋์ญ์ AOP - @Transactional ์ฌ์ฉ (0) | 2023.04.05 |
Spring์ ์ฌ์ฉํ์ง ์๊ณ Transaction ํด๊ฒฐ (0) | 2023.04.04 |
์ปค๋ฅ์ ํ by using DataSource Interface (0) | 2023.04.03 |
JDBC by using DriverManager (0) | 2023.04.02 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422