使用Spring(3.0.5),Hibernate(3.6.0)和Wicket(1.4.14)开发应用程序时遇到了一个奇怪的问题。问题是:我无法将任何对象保存或修改到数据库中。“不能”是指对象的所有更改或对EntityManager.persist(foo)的调用都被简单,无声地忽略。选择工作。
示例案例很简单-在某些检票页面上,我尝试将对象保存到数据库中,如下所示
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
当然,没有对象被保存到数据库中。
最后一个文件-我的应用程序COntext.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的目的。
a)您正在定义Hibernate SessionFactory和JPA EntitymanagerFactory。会是什么?使用Hibernate作为提供程序的Hibernate的Session API或JPA的Entitymanager API,但不能两者都使用。
SessionFactory
EntitymanagerFactory
b)您已经定义了一个HibernateTransactionManager,但是由于您EntityManager在代码中使用,因此需要一个JpaTransactionManager:
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不应是事务性的。您应该使用管理事务的服务层。