一个事务中的Hibernate和JDBC

我有一个标记为@Transactional的方法。 它由几个函数组成,其中一个使用JDBC,第二个是Hibernate,第三个是JDBC。 问题是Hibernate函数所做的更改在最后一个与JDBC一起使用的函数中是不可见的。

@Transactional void update() { jdbcUpdate1(); hibernateupdate1(); jdbcUpdate2(); // results of hibernateupdate1() are not visible here } 

所有函数都配置为使用相同的数据源:

       

myDataSource bean用于代码中。 myDataSource.getConnection()用于处理jdbc函数和中的连接

 getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { ... } }); 

用于hibernate函数。 谢谢。

首先,避免在使用hibernate时使用JDBC。

然后,如果您真的需要它,请使用Session.doWork(..) 。 如果你的hibernate版本还没有这个方法,请从session.connection()获取Connection

如果使用正确的Spring设置,则可以在同一事务中使用JDBC和Hibernate:

                 PROPAGATION_SUPPORTS,readOnly PROPAGATION_REQUIRED    

这假设您的DAO的JDBC部分使用JdbcTemplate。 如果没有,你有几个选择:

  • 使用DataSourceUtils.getConnection(javax.sql.DataSource)获取连接
  • 使用TransactionAwareDataSourceProxy将传递给您的DAO的数据源(但不一定是传递给SessionFactory的数据源)包装起来

后者是首选,因为它隐藏了代理数据源中的DataSourceUtils.getConnection。

这当然是XML路径,应该很容易将其转换为基于注释。

问题是,Hibernate引擎的操作不会导致立即执行SQL。 你可以在Hibernate会话上手动调用flush来触发它。 然后,在同一事务中,SQL代码可以看到在hibernate中所做的更改。 只要你做DataSourceUtils.getConnection来获得SQL连接,因为只有这样你才能让他们在同一个事务中运行…

在相反的方向上,这更棘手,因为你有一级缓存(会话缓存),也可能是二级缓存。 对于二级缓存,如果缓存行,则对Hibernate的所有更改都将对Hibernate不可见,直到缓存过期。