经过将近10个小时的搜索和尝试不同的事情,我无法弄清楚,问题的主要原因是什么。所以,也许有人可以帮助我。我正在学习Spring + JPA。我有EAR项目(在Eclipse中)包含两个项目:JPA和Servlets。该EAR正在部署在Glassfish应用服务器上。
JPA项目: Bean,Services和DAO。
Servlet项目:只有一个简单的HttpRequestHandlerServlet,从JPA调用服务。
问题:在servlet端,从dao(通过服务)获取数据工作正常。存储数据正在提升TransactionRequiredException
。
@PersistenceContext
EntityManager em;
@Transactional
public void persist(Employee entity) {
em.persist(entity);
em.flush();
}
}
@Autowired
private EmployeeDao dao;
public Employee store(Employee in) {
dao.persist(in);
return in;
}
<tx:annotation-driven transaction-manager="transactionManager" />
<context:annotation-config />
<context:load-time-weaver />
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/test" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="testJPA" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="employeeDao" class="... EmployeeDaoImpl" />
<bean id="employeeService" class="... EmployeeServiceImpl">
<property name="employeeDao" ref="employeeDao" />
</bean>
<bean id="serviceContext"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:services.xml</value>
</list>
</constructor-arg>
</bean>
<persistence-unit name="testJPA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/test</jta-data-source>
<class>... entity.Employee</class>
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
<context-param>
<param-name>parentContextKey</param-name>
<param-value>serviceContext</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/Test</url-pattern>
</servlet-mapping>
<bean id="test" class="... TestServlet">
<property name="employeeService" ref="employeeService" />
</bean>
在测试servlet中,调用employeeService.store( ... )
会引发异常:
WARNING: StandardWrapperValve[test]: PWC1406: Servlet.service() for servlet testt threw exception
javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently active for this thread
at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:86)
at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.checkForTransaction(JTATransactionWrapper.java:46)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1776)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
em.flush()
引发了问题。我试图通过放置在Servlet项目中初始化我的层次化上下文中的某个地方找到问题,我还在servlet项目的ApplicationContext.xml中只尝试了一个bean定义。这些都不起作用,所以问题可能在其他地方。
非常感谢任何评论,关心Z。
答案 0 :(得分:1)
首先,考虑直接在DAO级别上标记@Transactional
在设计上被认为有点不明智 - 通常,事务跨越服务层,因此建议仅在服务层上进行事务划分。 / p>
其次,虽然我还没有直接使用EclipseLink JPA实现,但从这个例外情况来看,您已尝试启动全局事务,但尚未配置全局(JTA)事务管理器实现。 / p>
您的配置似乎也暗示了这一点:
org.springframework.orm.jpa.JpaTransactionManager
),<jta-data-source>jdbc/test</jta-data-source>
)如果您需要使用本地事务(在95%的情况下就是这种情况),您必须使用以下内容为LOCAL事务配置JPA提供程序:
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>jdbc/test</non-jta-data-source>
</persistence-unit>
如果全局事务是您确实需要的,那么您将需要在Spring上下文中注入不同的事务管理器实现。有关如何配置此方案的更详细说明取决于实际实现本身 - 我想到的两个免费提供的是Atomikos和Bitronix。它们都很好地与Spring集成,并且有很好的文档记录。
答案 1 :(得分:1)
我换了:
我的配置工作没有任何更改。