2011-03-21 51 views
2

我在使用Spring(3.0.5),Hibernate(3.6.0)和Wicket(1.4.14)開發應用程序時遇到了奇怪的問題。問題是:我無法將任何對象保存或修改爲數據庫。通過'不能'我的意思是對象的所有變化或對EntityManager.persist(foo)的調用都是簡單地,默默地忽略。選擇工作。在Spring @Transactional方法中沒有開始交易

樣品的情況下很簡單 - 一些檢票頁我試圖保存對象到數據庫中,像如下

public class ComicDetailsPage extends PublicBasePage { 

@Override 
protected void onConfigure() { 
    System.out.println("In onConfigure"); 
    super.onConfigure(); 
    comicDAO.insert("abc"); 

} 

@SpringBean(name="comicDAO") 
private ComicDAO comicDAO; 

    (....) 

這裏是comicDAO

@Service 
public class ComicDAO { 

@PersistenceContext 
private EntityManager em; 

(...) 

@Transactional 
public void insert(String title) { 
    Comic c = new Comic(); 
    c.setTitle(title); 
    em.persist(c); 
} 

@Transactional 
public Comic add1toTitle(int pk) { 
    System.out.println("Beginning fetching"); 
    Comic c = em.find(Comic.class, pk); 
    System.out.println("Fetched updating"); 
    c.setTitle(c.getTitle()+"1"); 
    System.out.println("Updated persisting"); 
    em.persist(c); 
    System.out.println("Persisted returning"); 
    return c; 
} 

我打開日誌記錄,並在這裏是有關部分日誌(Hibernate和Spring都設置爲TRACE)。我在這裏添加了**,我認爲這很重要。

In onConfigure 
01:53:19.330 [qtp2119047503-15] DEBUG o.s.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'txManager' 
**01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13006687993** 
**01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - begin** 
01:53:19.330 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection 
01:53:19.335 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - current autocommit status: true 
01:53:19.335 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - disabling autocommit 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction begin 
01:53:19.336 [qtp2119047503-15] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13006687993 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - setting flush mode to: AUTO 
01:53:19.336 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - setting cache mode to: NORMAL 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.engine.IdentifierValue - id unsaved-value: 0 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.event.def.AbstractSaveEventListener - transient instance of: pl.m4ks.comics.entity.Comic 
01:53:19.337 [qtp2119047503-15] TRACE org.hibernate.event.def.DefaultPersistEventListener - saving transient instance 
**01:53:19.338 [qtp2119047503-15] TRACE org.hibernate.event.def.AbstractSaveEventListener - saving [pl.m4ks.comics.entity.Comic#<null>]** 
**01:53:19.341 [qtp2119047503-15] DEBUG org.hibernate.event.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress** 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - closing session 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.jdbc.ConnectionManager - connection already null in cleanup : no action 
01:53:19.341 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - commit 
**01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - automatically flushing session** 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - before transaction completion 
01:53:19.341 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - before transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - re-enabling autocommit 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.transaction.JDBCTransaction - committed JDBC Connection 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - after transaction completion 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - closing session 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.ConnectionManager - performing cleanup 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 
01:53:19.342 [qtp2119047503-15] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
01:53:19.342 [qtp2119047503-15] TRACE org.hibernate.impl.SessionImpl - after transaction completion 

當然沒有對象被保存到數據庫中。

的最後一個文件 - 我的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans (...)> 

    <context:component-scan base-package="pl.m4ks.comics"/> 
    <context:annotation-config /> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
     <property name="driverClass" value="com.mysql.jdbc.Driver"/> 
     <property name="url" value="jdbc:mysql://localhost:8889/comics" /> 
     <property name="username" value="root"/> 
     <property name="password" value="root" />   
    </bean> 

    <bean id="entityManagerFactory" 
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="main" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource"> 
      <ref bean="dataSource"/> 
     </property> 
     <property name="packagesToScan"> 
      <value>pl.m4ks.comics</value> 
     </property> 
    </bean> 


    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> 
</beans> 

我不知道有什麼可以是問題,以及如何解決它。我不想在我的代碼中管理事務 - 這就是Spring的用處。

+0

wicket類中dao的實際類型是什麼(system .getClass())。 DAO有什麼構造函數? – Bozho 2011-03-21 01:21:18

+0

刪除了wicket標籤,因爲它與此問題無關(您的問題不在您的檢票代碼中)。添加了Java和JPA標籤 – 2011-03-21 10:00:51

回答

13

a)您正在定義既一個Hibernate SessionFactory和JPA EntitymanagerFactory。這將是什麼?可以使用Hibernate的Session API或JPA的Entitymanager API作爲提供者,但不能同時使用兩者。

b)您已經定義了一個HibernateTransactionManager,但因爲你在你的代碼中使用EntityManager,你需要一個JpaTransactionManager來代替:

<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="myEmf"/> 
</bean 

這是你的applicationContext.xml的註釋版本:

<?xml version="1.0" encoding="UTF-8"?> 
<beans (...)> 

    <context:component-scan base-package="pl.m4ks.comics"/> 
    <context:annotation-config /> 

    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
     <property name="driverClass" value="com.mysql.jdbc.Driver"/> 
     <property name="url" value="jdbc:mysql://localhost:8889/comics" /> 
     <property name="username" value="root"/> 
     <property name="password" value="root" />   
    </bean> 

    <!-- use either this: --> 
    <bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="main" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <!-- or this --> 
    <bean id="sessionFactory" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource"> 
      <ref bean="dataSource"/> 
     </property> 
     <property name="packagesToScan"> 
      <value>pl.m4ks.comics</value> 
     </property> 
    </bean> 
    <!-- (but not both) --> 

    <!-- this is correct for AnnotationSessionFactoryBean, but not if you use 
     LocalContainerEntityManagerFactoryBean --> 
    <bean id="txManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 

    <!-- not necessary, <context:annotation-config /> automatically includes this --> 
    <bean 
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> 
</beans> 

還有一個設計說明:DAO不應該是事務性的。您應該使用管理交易的服務層。請參閱this question(和許多其他)以供參考。

+0

非常感謝您的回答。我試圖編輯applicationCOntext。xml - 我剛纔評論了entityManagerFactory bean。現在我得到 'org.springframework.beans.factory.NoSuchBeanDefinitionException:沒有定義[javax.persistence.EntityManagerFactory]類型的唯一bean:預期的單個bean,但發現0,因爲我嘗試在我的DAO中使用entityManager。 – M4ks 2011-03-21 20:22:54

+0

@ M4ks那麼你應該註釋掉SessionFactory,而不是我想的EntityManagerFactory – 2011-03-21 20:25:11

+0

。但是,我怎樣才能執行任何數據庫操作沒有entityManager? – M4ks 2011-03-21 20:27:24

-3

你需要調用EntityManager的

flush()

以下方法來進行實際保存在數據庫

+2

這是不正確的。如果Spring TransactionManager設置正確,entityManager.flush()會自動調用 – 2011-03-21 09:45:23

0

您是否嘗試過在hibernate配置中設置hibernate.connection.autocommit = true?這將解決問題。但是這種方法的有效性是你必須弄清楚的。