2011-09-19 70 views
1

我想通過基於註釋的交易將hibernate集成到我的第一個Spring web項目中。但是,這不起作用,因爲我注意到保存查詢沒有提交。基於註釋的交易不起作用 - 春天3

這是AOP配置:

<context:annotation-config /> 
<context:component-scan base-package="package.names.project.controller" /> 
<context:component-scan base-package="package.names.project.model" /> 
<context:component-scan base-package="package.names.common.util" /> 

<aop:aspectj-autoproxy> 
    <aop:include name="Logger" /> 
</aop:aspectj-autoproxy> 

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean 
    below) --> 
<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <!-- the transactional semantics... --> 
    <tx:attributes> 
     <!-- other methods use the default transaction settings (see below) --> 
     <tx:method name="save" read-only="false"/> 
     <tx:method name="*" rollback-for="Exception" /> 
    </tx:attributes> 
</tx:advice> 

<!-- ensure that the above transactional advice runs for any execution of 
    an operation defined by a service in the service package --> 
<aop:config> 
    <aop:pointcut id="serviceOperations" expression="execution(* package.names.project.dao.*.*(..))" /> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperations" /> 
</aop:config> 

<!-- similarly, don't forget the PlatformTransactionManager --> 
<bean id="txManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 


<bean id="Logger" class="package.names.common.aop.Logger" /> 
<tx:annotation-driven transaction-manager="txManager" /> 

我有以下hibernate配置:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
<session-factory> 
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> 
    <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/db</property> 
    <property name="hibernate.connection.username">user</property> 
    <property name="connection.password">pass</property> 
    <property name="connection.pool_size">1</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> 
    <property name="show_sql">true</property> 
    <property name="hbm2ddl.auto">update</property> 
      <property name="connection.autocommit">true</property> 

    <mapping class="package.names.model.Person" /> 
</session-factory> 
</hibernate-configuration> 

bean聲明:

<bean id="personDao" class="package.names.project.dao.PersonDaoImpl"></bean> 
<bean id="dbService" class="package.names.project.service.DbService"></bean> 

我的服務層看起來像這樣

改變了一個SessionFactory的吾道一自動連接一個:

public class PersonDaoImpl implements PersonDao { 
    @Autowired 
    SessionFactory factory; 

    public void setFactory(SessionFactory factory){ 
     this.factory = factory; 
    } 

    public Long save(String personName, Integer personAge) { 
     Long personId = null; 
     Session session = factory.openSession(); 
     System.out.println(TransactionSynchronizationManager.isActualTransactionActive()); 
     Person person = new Person(); 
     person.setName(personName); 
     person.setAge(personAge); 
     session.saveOrUpdate(person); 
     session.close(); 
     return personId; 
    }.. 

只是有沒有標誌的事務被提交。 (當show-sql爲true時,不顯示插入語句)沒有錯誤消息來清除它。

(如果我添加 'session.beginTransaction()提交()' 我的保存()函數,它會工作,但似乎對聲明式事務管理的原則。)

UPDATE:

數據庫連接正常工作,就像listPerson()方法一樣。

我可以確認交易是活躍在保存方法和保存方法用於通過使用

logger.info(TransactionSynchronizationManager.isActualTransactionActive()) 

而且我可以看到autocommitting設置爲true的記錄:

INFO: autocommit mode: true 

我甚至在控制器和dao之間創建了一個服務層,以確保它不是導致問題的dao層。我用

@Transactional(readOnly = false) 

要確定問題不是由只讀模式引起的。 還剩什麼可嘗試?

UPDATE 2: 修復了這個問題。這是每次調用方法保存時打開一個新會話引起的。現在我只使用factory.openSession()一次,之後使用factory.getCurrentSession()並且不關閉會話。

+0

你不需要調用'openSession' - Spring爲你處理所有這些。總是調用'getSession'。 – atrain

回答

1

ApplicationContext實現的默認行爲是 在啓動時急切地預先實例化所有單例bean。

由於您的異常抱怨急於加載,請嘗試爲您的Spring bean添加lazy-init="true"屬性。

實施例:

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager" lazy-init="true"> 
    <property name="sessionFactory" ref="mySessionFactory" /> 
</bean> 

有關延遲初始化see更多的信息。

編輯

而且解決您提交的問題,嘗試添加下面的datasource設置:

<property name="defaultAutoCommit" value="true" /> 
+0

非常感謝。這確實解決了衝突aop配置的最後一個問題。 第一個問題依然存在。 – Jonathan

+0

請參閱編輯答案。 – Bitmap

1

要使用@Transactional你的bean必須通過Spring容器進行訪問。在提供的示例中,我沒有看到任何會顯示如何創建此bean的內容。你必須有

<context:component-scan base-package="package.names"/> 

<bean class="package.names.PersonDaoImpl"/> 

然後你就必須或者通過自動裝配或getBean()獲得從容器中的Bean。

那麼你如何在應用程序中獲得你的DAO bean實例呢?此外,看到bean類聲明以及接口會很有幫助。當事務性代理由於某些特定的類關係而未正確創建時,我確實有過這種情況。