스프링에서 하이버네이트와 JDBC 같이 사용할 때 트랜잭션 처리는?
별로 할 일이 없습니다.
PlatformManager는 하이버네이트가 사용하는
org.springframework.orm.hibernate3.HibernateTransactionManager
이걸 그대로 사용하면 되고, JDBC 코딩을 할 때는 그냥 JdbcTemplate을 사용하면 알아서 트랜잭션이 적용됩니다.
그런데 만약에 JdbcTemplate을 사용하지 못하고, DataSource를 직접 사용해야 할 경우에는 다음과 같이 TransactionAwareDataSourceProxy를 사용하면 된다고 합니다.
<bean id="dataSource" class="TransactionAwareDataSourceProxy">
<constructor-arg ref="rawDataSource" />
</bean>
DataSource를 직접 사용하는 코드가 엄청나게 많아서 손을 못댈 경우에는 저렇게 dataSource를 스프링이 관리하는 트랜잭션을 알고 있는 데이터소스로 바꾸면 된다고 하는데, 해보진 않았습니다. 제가 해보고 싶었던 건 하이버네이트가 flush()를 하지 않은 데이터에 대한 JDBC쿼리로 인한 예외 상황인데...
테스트를 잘못 짠건지.. 잘 안 되더군요.
public class MemberDao {
@Autowired
SessionFactory sessionFactory;
SimpleJdbcTemplate jdbcTemplate;
@Autowired
public MemberDao(DataSource dataSource) {
jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
public void add(Member member){
sessionFactory.getCurrentSession().save(member);
}
public int update(Member member){
return jdbcTemplate.update(
"UPDATE Member SET age = ? WHERE name = ?", member.getAge(), member.getName());
}
}
이런 DAO를 만들었습니다. add()는 하이버네이트로하고 update()는 JdbcTemplate으로 했습니다.
@Transactional
public class MemberService {
@Autowired
MemberDao memberDao;
public void foo(){
Member member = new Member();
member.setName("keesun");
memberDao.add(member);
member.setAge(20);
memberDao.update(member);
}
}
그리고 서비스 코드는 저렇게 트랜잭션 처리를 하고, keesun이라는 객체를 하나 만들어서 저장하고, 나이를 추가한다음에 JDBC로 update문을 날립니다.
제가 원했던 결과는..
에러가 나는 겁니다.
그러나..
Hibernate: insert into Member (age, name, id) values (?, ?, ?)
Hibernate: update Member set age=?, name=? where id=?
에러가 나질 않고, 너무도 자연스럽게 동작해버려서 당황했습니다. 특히 마지막 줄의 쿼리는 제가 JdbcTemplate으로 날린 쿼리랑은 완전 다른 하이버네이트가 만든 쿼리가 날아갔습니다. 이게 대체;;; 무슨 일인지.. 흠..
결과적으로는 아~무 걱정없이 하이버네이트랑 JdbcTemplate을 같이 사용할 수 있다는 것이지만, 제가 원했던 상황이 발생하지 않아서 좀 우울합니다.