日期:2014-05-16  浏览次数:20401 次

Hibertnate与JDBC混合使用

Hibernate与JDBCtemplate如何混用?
一开始在项目中使用的是Hibernate,但是发现Hibernate在做批量操作时,效率不是很理想。所以现在采用JDBCTemplate和Hibernate混用,现在问题是如何配置他们的事务?
两者都用同一个datasource ,同一spring管理事务就没有问题。

?

另外要注意两点:

1. 由于Spring JDBC 框架,它没有采用服务层缓存技术,所以可以使用 DAO 类返回数据库中的数据。如果采用 Hibernate 等 ORM 框架,由于它们采用了服务层缓存的技术,为了获取数据库中的相应数据,需要在业务方法执行后调用 HibernateTemplate.flush() 方法,将缓存中的对象同步到数据库中,这时才可以通过 SimpleJdbcTemplate 在数据库中访问业务方法的执行情况。

2. 使用hibernateTransaction manager ,才可以保证混用时候的事务。

?

补充:HibernateTransactionManager实际上是可以同时管理由JdbcTemplate或JdbcDaoSupport实现的dao以及HibernateTemplate或HibernateDaoSupport实现的事务的。

?


Spring 提供了一个能从当前事务上下文中获取绑定的数据连接的工具类,那就是 DataSourceUtils。Spring 强调必须使用 DataSourceUtils 工具类获取数据连接,Spring 的 JdbcTemplate 内部也是通过 DataSourceUtils 来获取连接的。DataSourceUtils 提供了若干获取和释放数据连接的静态方法,说明如下:

  • static Connection doGetConnection(DataSource dataSource) : 首先尝试从事务上下文中获取连接,失败后再从数据源获取连接;
  • static Connection getConnection(DataSource dataSource) : 和 doGetConnection 方法的功能一样,实际上,它内部就是调用 doGetConnection 方法获取连接的;
  • static void doReleaseConnection(Connection con, DataSource dataSource) :释放连接,放回到连接池中;
  • static void releaseConnection(Connection con, DataSource dataSource) :和 doReleaseConnection 方法的功能一样,实际上,它内部就是调用 doReleaseConnection 方法获取连接的;

来看一下 DataSourceUtils 从数据源获取连接的关键代码:

public abstract class DataSourceUtils {
    …
    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
        
		Assert.notNull(dataSource, "No DataSource specified");

        //①首先尝试从事务同步管理器中获取数据连接
        ConnectionHolder conHolder = 
            (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (conHolder != null && (conHolder.hasConnection() || 
            conHolder.isSynchronizedWithTransaction())) { 
            conHolder.requested();
            if (!conHolder.hasConnection()) {
                logger.debug(
                    "Fetching resumed JDBC Connection from DataSource");
                conHolder.setConnection(dataSource.getConnection());
            }
			return conHolder.getConnection();
		}
        
		//②如果获取不到,则直接从数据源中获取连接
        Connection con = dataSource.getConnection();

        //③如果拥有事务上下文,则将连接绑定到事务上下文中
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            ConnectionHolder holderToUse = conHolder;
            if (holderToUse == null) {
				holderToUse = new ConnectionHolder(con);
			}
			else {holderToUse.setConnection(con);}
            holderToUse.requested();
			TransactionSynchronizationManager.registerSynchronization(
                new ConnectionSynchronization(holderToUse, dataSource));
			holderToUse.setSynchronizedWithTransaction(true);
			if (holderToUse != conHolder) {
				TransactionSynchronizationManager.bindResource(
                dataSource, holderToUse);
			}
		}
		return con;
	}
    …
}


?

另外还有hibernate的SessionFactoryUtils(iBatis同Jdbc).

?

关于JdbcTemplate的使用可以参考下面的一篇文