簡體   English   中英

一個事務中的Hibernate和JDBC

[英]Hibernate and JDBC in one transaction

我有一個方法,標記為@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時使用JDBC。

然后,如果您真的需要它,請使用Session.doWork(..) 如果你的hibernate版本還沒有這個方法,請從session.connection()獲取Connection

問題是,Hibernate引擎的操作不會導致立即執行SQL。 你可以在Hibernate會話上手動調用flush來觸發它。 然后,在同一事務中的SQL代碼中可以看到hibernate中所做的更改。 只要你做DataSourceUtils.getConnection來獲得SQL連接,因為只有這樣你才能讓他們在同一個事務中運行...

在相反的方向上,這更棘手,因為你有一級緩存(會話緩存),也可能是二級緩存。 對於二級緩存,如果緩存行,則對Hibernate所做的所有更改都將對Hibernate不可見,直到緩存過期。

如果使用正確的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)獲取連接
  • 使用TransactionAwareDataSourceProxy將傳遞給您的DAO的數據源(但不一定是傳遞給SessionFactory的數據源)包裝起來

后者是首選,因為它隱藏了代理數據源中的DataSourceUtils.getConnection。

這當然是XML路徑,應該很容易將其轉換為基於注釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM