JDBC 기반 트랜잭션 처리 2. Business Layer에서 책임
참조 : Spring 프레임워크 워크북
이번에는 DAO 계층이 아닌 Service 계층으로 트랜잭션 책임을 다시 가져왔습니다. 따라서 서비스 계층이 이 전글에 비하면 좀 더 복잡해 졌습니다. 게다가 쌩 JDBC를 사용하고, 거기다 트랜잭션 처리도 AOP 사용해서 모듈화 하지 않았기 때문에 코드는 다음과 같이 다소 복잡합니다.
private MemberDao memberDao;
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public void add(Member member) throws SQLException {
Connection con = null;
try {
con = dataSource.getConnection();
con.setAutoCommit(false);
memberDao.add(con, member);
//TODO 예외발생
TransactionTestingUtil.generateSQLExceptionMethod();
con.commit();
}
catch (SQLException e) {
if(con != null)
con.rollback();
throw e;
}
finally {
if(con != null)
con.close();
}
}
}
add()메소드에서 해야할 일은 딱 두 줄(파란색)임에도 불구하고 여러 줄의 코드가 정신없이 널려있습니다. DAO 코드를 보겠습니다.
public void add(Member member) {
throw new UnsupportedOperationException();
}
public void add(Connection con, Member member) throws SQLException {
StringBuilder addMemberQuery = new StringBuilder();
addMemberQuery.append("INSERT INTO Member(id, password, name, email) ");
addMemberQuery.append("VALUES (?, ?, ?, ?)");
try {
PreparedStatement pstmt = con.prepareStatement(addMemberQuery.toString());
pstmt.setString(1, "whiteship3");
pstmt.setString(2, "pass");
pstmt.setString(3, "기선");
pstmt.setString(4, "keesun3@email.com");
pstmt.executeUpdate();
}
catch (SQLException e) {
throw e;
}
}
}
JDBC 코딩이 별로 재미도 없고 복잡합니다. 서비스 계층에서 사용하던 connection 객체를 그대로 이어 받아서 사용합니다. 그리고 만약 복잡한 SQL을 사용했을 떄 DB가 바껴버리면 그 복잡한 SQL들을 다 어떻게 관리할지 걱정이 됩니다.
테스트코드는 이전 글과 동일합니다. Spring 설정파일은 다음과 같습니다.
<property name="dataSource" ref="dataSource" />
<property name="memberDao" ref="memberDao" />
</bean>
<bean id="memberDao" class="com.bookbuying.member.dao.MemberDaoJdbcTransactionInBusiness" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${db.driver}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="user" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
다음 글에서는 Spring의 Transaction 관련 주요 API들(TransactionDefinition, TransactionStatus, PlatformTransactionManager)을 사용하여 구현하겠습니다.