所有,我正在尝试在 Spring 中使用注释事务并获取 javax.persistence.TransactionRequiredException: no transaction is in progress
一直出错。
错误堆栈跟踪:
[22:40:11:354] 00000024 SystemErr R javax.persistence.TransactionRequiredException: no transaction is in progress
[22:40:11:354] 00000024 SystemErr R at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
[22:40:11:354] 00000024 SystemErr R at java.lang.reflect.Method.invoke(Method.java:611)
[22:40:11:354] 00000024 SystemErr R at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
[22:40:11:354] 00000024 SystemErr R at $Proxy45.flush(Unknown Source)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
[22:40:11:354] 00000024 SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
[22:40:11:354] 00000024 SystemErr R at java.lang.reflect.Method.invoke(Method.java:611)
[22:40:11:354] 00000024 SystemErr R at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
[22:40:11:354] 00000024 SystemErr R at $Proxy42.flush(Unknown Source)
[22:40:11:354] 00000024 SystemErr R at com.test.MyDAO.saveOrUpdateData
.
.
.
请注意,当我使用 AOP 时,相同的代码运行良好。
技术栈如下所示:
Spring 3.0.5
Struts 2.2.1.1
Hibernate 3.3.2GA
JPA 1.0
JBPM 4.4
这是我的应用程序配置:
应用程序上下文.xml
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- <bean-->
<!-- class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />-->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/my_dataSource1.1"
cache="true" resource-ref="true" lookup-on-startup="true"
proxy-interface="javax.sql.DataSource" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceXmlLocation" value="META-INF/my-persistence.xml" />
</bean>
<!--
Also tried the JTA transaction manager....
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
-->
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
<tx:annotation-driven/>
<!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">-->
<!-- <tx:attributes>-->
<!-- <tx:method name="get*" read-only="true" />-->
<!-- <tx:method name="saveOrUpdate*" propagation="REQUIRES_NEW" read-only="false"/>-->
<!-- </tx:attributes>-->
<!-- </tx:advice>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="daoOperations"-->
<!-- expression="execution(* com.honda.naps.dao..*.*(..))" />-->
<!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperations" />-->
<!-- </aop:config>-->
<!-- This is the DAO that's injected -->
<bean id="myDAO" class="com.test.MyDAO" />
<bean id="myBaseDAO" class="com.test.BaseDAO" />
<!--
This is the struts action that's created .. in struts.xml I have used
<constant name="struts.objectFactory" value="spring" />
-->
<bean id="myAction" scope="prototype" class="com.test.MyAction">
</bean>
<!-- My BO instance -->
<bean id="myBO" class="com.test.MyBOImpl">
<property name="myDAO" ref="myDAO" />
<property name="myBaseDAO" ref="myBaseDAO" />
</bean>
</beans>
同样在 struts.xml 中,我调用 MyDAO 类的 saveOrUpdateData()。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" metadata-complete="true">
<display-name>NAPSWeb</display-name>
<context-param>
<param-name>
org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/resources/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>1000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring_config/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<distributable></distributable>
</web-app>
我的持久性.xml
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> org.hibernate.ejb.HibernatePersistence jdbc/my_dataSource1.1
<class>com.test.MyTbl1</class>
<class>com.test.MyTbl2</class>
<class>com.test.MyTbl3</class>
<properties>
<!-- HIBERNATE properties -->
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<!-- <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/> -->
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereTransactionManagerLookup"/>
<property name="jta.UserTransaction" value="java:comp/UserTransaction"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>-->
<property name="hibernate.showsql" value="true"/>
<!-- <property name="hibernate.cache.use_second_level_cache" value="false"/> -->
<!-- <property name="jta.UserTransaction" value="java:comp/UserTransaction"/> -->
<property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect"/>
</properties>
</persistence-unit>
使用@Transactional 的DAO 方法类如下所示:
//MyDAO 类
public class MyDAO extends BaseDAO
{
@Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=false)
public void saveOrUpdateData()
{
MyTbl1 mt1 = new MyTbl1();
//do something with mt1
getEntityManager().persist(mt1);
getEntityManager().flush();
}
}
BaseDAO 类:
public class BaseDAO {
/**
* Variable which stores the injected
* JPA Entity Manager.
*/
private EntityManager entityManager;
public EntityManager getEntityManager() {
System.out.println("getting the entity manager.");
return entityManager;
}
@PersistenceContext(unitName="MY_JPA")
public void setEntityManager(EntityManager entityManager) {
logger.debug("Setting the entity manager.");
this.entityManager = entityManager;
}
}
使用的库:
ejb3-persistence.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
hibernate3.3.2.GA.jar
antlr-2.7.6.jar
aopalliance-1.0.jar
asm-1.5.3.jar
asm-all-2.2.3.jar
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar
commons-beanutils-1.8.0.jar
commons-collections-3.1.jar
commons-digester-1.8.1.jar
commons-io-1.3.2.jar
commons-logging-1.0.4.jar
commons-logging-api-1.1.jar
dom4j-1.6.1.jar
freemarker-2.3.8.jar
javassist-3.12.0.GA.jar
jbpm.jar
juel-api.jar
juel-engine.jar
juel-impl.jar
log4j-1.2.16.jar
ognl-3.0.jar
org.springframework.aop-3.0.5.RELEASE.jar
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.aspects-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.context.support-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
org.springframework.jdbc-3.0.5.RELEASE.jar
org.springframework.orm-3.0.5.RELEASE.jar
org.springframework.transaction-3.0.5.RELEASE.jar
org.springframework.web-3.0.5.RELEASE.jar
slf4j-api-1.6.1.jar
slf4j-nop-1.6.1.jar
struts2-convention-plugin-2.2.1.1.jar
struts2-core-2.2.1.1.jar
struts2-dojo-plugin-2.2.1.1.jar
struts2-json-plugin-2.2.1.jar
struts2-spring-plugin-2.2.1.1.jar
struts2-tiles-plugin-2.1.6.jar
tiles-api-2.1.2.jar
tiles-compat-2.1.2.jar
tiles-core-2.1.2.jar
tiles-jsp-2.1.2.jar
tiles-servlet-2.1.2.jar
xwork-core-2.2.1.1.jar
系统配置:
Websphere App server TE 7.0.0.15 in RAD IDE 7.5
OS: Windows XP SP3
DB: MS SQL Server 2008 enterprise edition
我启用了 parent_last 类加载,并在我的 Websphere 应用程序服务器中将默认 JPA 提供程序分配为“org.hibernate.ejb.HibernatePersistence”。
任何帮助表示赞赏。
谢谢
========================================
添加这个供大家使用...
我最终不得不使用基于 AOP 的事务管理。我找不到让@Transactional 在我的应用程序中工作的方法。
在我为 AOP 集成添加到我的应用程序的部分下方添加(在 applicationContext.xml 中):
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="saveOrUpdate*" propagation="REQUIRES_NEW" read-only="false"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoOperations"
expression="execution(* com.test..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperations" />
</aop:config>
希望这可以帮助,