Spring @Transactional方法中没有事务启动

M4k*_*4ks 2 java spring hibernate jpa transactional

我在使用Spring(3.0.5),Hibernate(3.6.0)和Wicket(1.4.14)开发应用程序时遇到了奇怪的问题.问题是:我无法将任何对象保存或修改为数据库.通过'不能',我的意思是对象的所有更改或对EntityManager.persist(foo)的调用都被简单地,默默地忽略.选择工作.

示例案例很简单 - 在一些wicket页面上我尝试将对象保存到数据库中,如下所示

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;

    (....)
Run Code Online (Sandbox Code Playgroud)

这是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;
}
Run Code Online (Sandbox Code Playgroud)

我打开了日志记录,这里是日志的相关部分(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
Run Code Online (Sandbox Code Playgroud)

当然没有对象保存到数据库中.

最后一个文件 - 我的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>
Run Code Online (Sandbox Code Playgroud)

我不知道可能是什么问题以及如何解决它.我不想在我的代码中管理事务 - 这就是Spring的用途.

Sea*_*oyd 13

a)您正在定义Hibernate SessionFactory和JPA EntitymanagerFactory.它会是什么?要么使用Hibernate的Session API,要么使用JPA的Entitymanager API和Hibernate作为提供者,但不能同时使用两者.

b)您已定义了a HibernateTransactionManager,但由于您EntityManager在代码中使用了,因此需要使用JpaTransactionManager:

<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf"/>
</bean
Run Code Online (Sandbox Code Playgroud)

这是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>
Run Code Online (Sandbox Code Playgroud)

设计说明:DAO不应该是交易性的.您应该使用管理事务的服务层.请参阅此问题(以及许多其他问题)以供参考.