Java Hibernate和JDBC在一个事务中
我有一个方法,标记为@Transactional。 它由几个函数组成,其中一个使用JDBC,第二个使用Hibernate,第三个使用JDBC。 问题是Hibernate函数所做的更改在最后一个使用JDBC的函数中不可见Java Hibernate和JDBC在一个事务中,java,hibernate,spring,jdbc,transactions,Java,Hibernate,Spring,Jdbc,Transactions,我有一个方法,标记为@Transactional。 它由几个函数组成,其中一个使用JDBC,第二个使用Hibernate,第三个使用JDBC。 问题是Hibernate函数所做的更改在最后一个使用JDBC的函数中不可见 @Transactional void update() { jdbcUpdate1(); hibernateupdate1(); jdbcUpdate2(); // results of hibernateupdate1() are not visible here
@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>
在hibernate函数中使用。
谢谢。首先,在使用hibernate时避免使用JDBC
然后,如果你真的需要它,使用它。如果您的hibernate版本还没有此方法,请从
session.Connection()
获取连接。如果使用正确的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(javax.sql.DataSource)获取连接
- 用TransactionWareDatasourceProxy包装传递给DAO的数据源(但不一定是传递给SessionFactory的数据源)
后者是首选,因为它将DataSourceUtils.getConnection隐藏在代理数据源中
这当然是XML路径,将其转换为基于注释的路径应该很容易。问题是,Hibernate引擎上的操作不会导致立即执行SQL。您可以在Hibernate会话上通过调用flush
手动触发它。然后,在hibernate中所做的更改将对同一事务中的SQL代码可见。只要您执行DataSourceUtils.getConnection
来获取SQL连接,因为只有这样您才能让它们在同一事务中运行
在相反的方向,这是更棘手的,因为您有1级缓存(会话缓存),也可能有2级缓存。对于二级缓存,如果缓存了行,则对数据库所做的所有更改对Hibernate都将不可见,直到缓存过期 对于那些从谷歌来到这里的人,我的解决方案。我在hibernate flush函数的末尾添加了session.flush()。之后,它的写入结果将在下一个jdbc读取函数(在同一事务中)中可用。
<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>