以前在做spring security时,就注意到一个细节,那就是当我只使用spring核心功能与hibernate时,居然也要依赖于spring-jdbc包,至少会报以下错误:
org/springframework/jdbc/support/SQLExceptionTranslator
当时并不在意这个,少就加上嘛,现在想来,的确有些奇怪,session、transaction之类的应该是hibernate自带的,怎么还要依赖于spring jdbc包,今天花了点时间看了下spring jdbc,但是奇怪的是,并没有spring jdbc中发现有处理事物的类与方法,那spring jdbc是怎么处理事务的呢?首先要做的就是在网上找资料,有前辈已经分析了,然后自己看了一下源码,的确是那样的,那就是hibernate与spring jdbc进行事务控制的是同一个类。在HibernateTransactionManager中的确有这么个注释:
* <p>This transaction manager is appropriate for applications that use a single
* Hibernate SessionFactory for transactional data access, but it also supports
* direct DataSource access within a transaction (i.e. plain JDBC code working
* with the same DataSource). This allows for mixing services which access Hibernate
* and services which use plain JDBC (without being aware of Hibernate)!
* Application code needs to stick to the same simple Connection lookup pattern as
* with {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
* (i.e. {@link org.springframework.jdbc.datasource.DataSourceUtils#getConnection}
* or going through a
* {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy}).
在此类的doBegin方法中,有一段代码说得比较具体:
...
// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
if (getDataSource() != null) {
Connection con = session.connection();
ConnectionHolder conHolder = new ConnectionHolder(con);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
conHolder.setTimeoutInSeconds(timeout);
}
if (logger.isDebugEnabled()) {
logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
}
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
txObject.setConnectionHolder(conHolder);
}
...
从上面的第一个if语句中可以看出,只要jdbcTemplate与hibernateTemplate使用的是同一个dataSource,那么就可以达到控制事物的目的,这也说明了为什么hibernateDaoSupport为什么要依赖spring jdbc,因为它的底层事物控制也要依赖于spring jdbc的事物控制,而不是hibernate的底层事物控制。