我有一个标记为@Transactional的方法。 它由几个函数组成,其中一个使用JDBC,第二个是Hibernate,第三个是JDBC。 问题是Hibernate函数所做的更改在最后的函数中是不可见的,这些函数适用于JDBC。
@Transactional
void update() {
jdbcUpdate1();
hibernateupdate1();
jdbcUpdate2(); // results of hibernateupdate1() are not visible here
}
所有功能都配置为使用相同的数据源:
<bean id="myDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="targetDataSource"/>
</bean>
<bean id="targetDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" lazy-init="true" scope="singleton">
<!-- settings here -->
</bean>
myDataSource bean用于代码中。 myDataSource.getConnection()用于处理jdbc函数和
中的连接getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
...
}
});
用于hibernate函数。 感谢。
答案 0 :(得分:11)
首先,避免在使用hibernate时使用JDBC。
然后,如果您真的需要它,请使用Session.doWork(..)
。如果你的hibernate版本还没有这个方法,请从Connection
获取session.connection()
。
答案 1 :(得分:2)
如果使用正确的Spring设置,则可以在同一事务中使用JDBC和Hibernate:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="myDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target">
<bean class="MyDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
这假设DAO的JDBC部分使用JdbcTemplate。如果没有,你有几个选择:
后者是首选,因为它隐藏了代理数据源中的DataSourceUtils.getConnection。
这当然是XML路径,应该很容易将其转换为基于注释。
答案 2 :(得分:2)
问题是,在立即执行SQL时,Hibernate引擎上的操作不会导致。你可以在Hibernate会话上手动调用flush
来触发它。然后,在同一事务中的SQL代码中可以看到hibernate中所做的更改。只要你DataSourceUtils.getConnection
获得SQL连接,因为只有这样你才能让它们在同一个交易中运行 ......
在相反的方向上,这更棘手,因为你有1级缓存(会话缓存),也可能是2级缓存。对于二级缓存,如果缓存行,则对Hibernate所做的所有更改都将对Hibernate不可见,直到缓存过期。