Spring @Transactional 没有创建所需的事务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2427223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring @Transactional not creating required transaction
提问by Steve
Ok, so I've finally bowed to peer pressure and started using Spring in my web app :-)...
好的,所以我终于屈服于同辈压力并开始在我的网络应用程序中使用 Spring :-)...
So I'm trying to get the transaction handling stuff to work, and I just can't seem to get it.
所以我试图让事务处理的东西工作,但我似乎无法得到它。
My Spring configuration looks like this:
我的 Spring 配置如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="groupDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao" lazy-init="true">
<property name="entityManagerFactory" ><ref bean="entityManagerFactory"/></property>
</bean>
<!-- enables interpretation of the @Required annotation to ensure that dependency injection actually occures -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<!-- enables interpretation of the @PersistenceUnit/@PersistenceContext annotations providing convenient
access to EntityManagerFactory/EntityManager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<!-- uses the persistence unit defined in the META-INF/persistence.xml JPA configuration file -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="CONOPS_PU" />
</bean>
<!-- transaction manager for use with a single JPA EntityManagerFactory for transactional data access
to a single datasource -->
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- enables interpretation of the @Transactional annotation for declerative transaction managment
using the specified JpaTransactionManager -->
<tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="true"/>
</beans>
persistence.xml:
持久性.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="CONOPS_PU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
... Class mappings removed for brevity...
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.connection.username" value="****"/>
<property name="hibernate.connection.password" value="*****"/>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@*****:1521:*****"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
The DAO method to save my domain object looks like this:
保存域对象的 DAO 方法如下所示:
@Transactional(propagation=Propagation.REQUIRES_NEW)
protected final T saveOrUpdate (T model)
{
EntityManager em = emf.createEntityManager ( );
EntityTransaction trans = em.getTransaction ( );
System.err.println ("Transaction isActive () == " + trans.isActive ( ));
if (em != null)
{
try
{
if (model.getId ( ) != null)
{
em.persist (model);
em.flush ();
}
else
{
em.merge (model);
em.flush ();
}
}
finally
{
em.close ();
}
}
return (model);
}
So I try to save a copy of my Group object using the following code in my test case:
所以我尝试在我的测试用例中使用以下代码保存我的 Group 对象的副本:
context = new ClassPathXmlApplicationContext(configs);
dao = (GroupDao)context.getBean("groupDao");
dao.saveOrUpdate (new Group ());
This bombs with the following exception:
这个炸弹有以下例外:
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:341)
at $Proxy26.flush(Unknown Source)
at mil.navy.ndms.conops.common.dao.impl.jpa.GenericJPADao.saveOrUpdate(GenericJPADao.java:646)
at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao.save(GroupDao.java:641)
at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao$$FastClassByCGLIB$343b9b.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao$$EnhancerByCGLIB$59ba58.save()
at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDaoTest.testGroupDaoSave(GroupDaoTest.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:230)
at junit.framework.TestSuite.run(TestSuite.java:225)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
In addition, I get the following warnings when Spring first starts. Since these reference the entityManagerFactory and the transactionManager, they probably have some bearing on the problem, but I've no been able to decipher them enough to know what:
此外,当 Spring 首次启动时,我收到以下警告。由于这些引用了 entityManagerFactory 和 transactionManager,因此它们可能对问题有一些影响,但我无法破译它们以知道什么:
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'entityManagerFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'entityManagerFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'jpaTransactionManager' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean '(inner bean)' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean '(inner bean)' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
INFO: Bean 'org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Mar 11, 2010 12:19:27 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@37003700: defining beans [groupDao,org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor,entityManagerFactory,jpaTransactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor]; root of factory hierarchy
Does anyone have any idea what I'm missing? I'm totally stumped...
有谁知道我错过了什么?我完全被难住了...
Thanks
谢谢
回答by axtavt
The instance of entity manager obtained from EntityManagerFactory.createEntityManager()doesn't participate in Spring-managed transactions.
从中获取的实体管理器实例EntityManagerFactory.createEntityManager()不参与 Spring 管理的事务。
The usual way to obtain an entity manager is to inject it using @PersistenceContext-annotated property:
获取实体管理器的常用方法是使用@PersistenceContext-annotated 属性注入它:
@PersistenceContext
public void setEntityManager(EntityManager em) { ... }
回答by skaffman
The problem is likely caused by a combination of you annotating a protected method, and using proxy-target-class="true". That's a bad mix. The transactional proxy generated by Spring will only work properly with public annotated methods, but it won't complain if they're not.
该问题可能是由您对受保护方法进行注释并使用proxy-target-class="true". 这是一个糟糕的组合。Spring 生成的事务代理只能与公共注释方法一起正常工作,但如果不是,它不会抱怨。
Try either making the saveOrUpdate()method public or, better yet, define an interface for your DAO, and remove the proxy-target-class="true"setting. This is the safest, most predictable technique.
尝试将saveOrUpdate()方法公开,或者更好的是,为您的 DAO 定义一个接口,然后删除proxy-target-class="true"设置。这是最安全、最可预测的技术。
回答by bsautner
In my case:
就我而言:
Using JPA with Spring MVC - all of my tests and code ran fine without error - symptom was that commits would simply not save to the database no matter what I tried.
在 Spring MVC 中使用 JPA - 我的所有测试和代码都运行良好,没有错误 - 症状是无论我尝试什么,提交都不会保存到数据库中。
I had to add to my applicationContext.xml and cglib-nodep-2.1_3.jar aopalliance-1.0.jar
我不得不添加到我的 applicationContext.xml 和 cglib-nodep-2.1_3.jar aopalliance-1.0.jar
Definitely the fix in my case. Without annotation-driven Spring will not scan for the @Transactional annotation
在我的情况下绝对是修复。没有注解驱动的 Spring 将不会扫描 @Transactional 注解

