3

我正在尝试设置以下组件:

  • EclipseLink 2.4.1
  • 春天 3.1.3
  • 玻璃鱼 3.1.2
  • Derby 嵌入式数据库

到目前为止,这些东西正在运行。但是一旦我想在我的 JPA 上下文中坚持一些东西,TransactionRequiredException就会抛出 a:

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction(EntityTransactionWrapper.java:50)
    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:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at $Proxy439.flush(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy439.flush(Unknown Source)
    at backend.dao.StoredObjectDAO.save(StoredObjectDAO.java:39)
    at backend.service.StorageService.setObjectForKey(StorageService.java:35)
    at backend.controller.StoredObjectController.setObjectForKey(StoredObjectController.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:680)

事务管理器的设置如各种教程中所述,甚至 Eclipse 通过在 linenumber 窗格旁边使用相关图标指示切入点来识别 aspectj 编织。因为我正在使用@Transactional注释,所以我正确设置<tx:annotaion-driven />为“on”。

但是,我仍然遇到同样的异常。有人知道在使用这些图书馆时是否需要特定的设置吗?请在下面找到所有必要的文件。

谢谢,马努


更新

终于离开了 Spring 并使用了另一个堆栈:

  • Google Guice(依赖注入)
  • 泽西岛(REST 库)
  • Eclipse 链接 (JPA)

我不得不继续,那个时候这个解决方案更加务实。也许再给春天一次机会。

无论如何,谢谢大家的所有投入!:-)


applicationContext-jpa.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:context="http://www.springframework.org/schema/context"
    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-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:load-time-weaver />
    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager" />

    <import resource="applicationContext-dataSource.xml" />

    <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
        <property name="databasePlatform" value="org.eclipse.persistence.platform.database.DerbyPlatform" />
        <property name="showSql" value="true" />
    </bean>
    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />



    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
        <property name="persistenceXmlLocation" value="classpath:/META-INF/persistence.xml"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaDialect" ref="jpaDialect" />
    </bean>



    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

</beans>

applicationContext-dataSource.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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">


    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/backend" />

</beans>

持久性.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="backend" transaction-type="JTA">
        <!-- 
            jta-data-source is only used for the IDE. Spring/Runtime uses the
            data source from applicationContext-dataSource.
        -->
        <jta-data-source>jdbc/backend</jta-data-source>

        <class>backend.model.StoredObject</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
    </persistence-unit>
</persistence>

StoredObjectDAO.java

@Repository
@Transactional
public class StoredObjectDAO implements IStoredObjectDAO {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional(readOnly = true)
    public Collection<StoredObject> listAll() {
        TypedQuery<StoredObject> query = entityManager.createQuery("select s from StoredObject s", StoredObject.class);
        Collection<StoredObject> results = query.getResultList();
        return results;
    }

    @Override
    public void save(StoredObject storedObject) {
        entityManager.persist(storedObject);
        entityManager.flush(); // <---- throws Exception
    }

}
4

8 回答 8

5

如果您从服务类调用 DAO 方法,请避免注释 DAO 方法 @Transactional。而是将您的 Service 类方法注释为事务性的。这背后的原因是,您可能需要在一个事务下调用多个 DAO 方法。如果您的所有 DAO 方法都是事务性的,这可能会导致问题。因此,如果您将服务方法注释为事务性的,则可以在一个事务下调用任意数量的 DAO 方法。

如果发生任何异常,如果您注释服务类事务,则整个事务将被回滚。

于 2012-11-09T07:12:30.257 回答
4

缺少使用readonly属性和propagation模式。默认propagation模式是REQUIRED. 这就是为什么,您的编码将假设如下,

@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public Collection<StoredObject> listAll() {
    ......
}

Point :使用传播模式 readonly时,连接会抛出异常。REQUIRED

答:如果您想使用readonly连接,propagation模式将是SUPPORTS

@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
    public Collection<StoredObject> listAll() {
    ......
}

供参考:交易策略

于 2012-11-09T07:35:16.657 回答
2

错误似乎 EclipseLink 正在使用 EntityTransactionWrapper 而不是 JTATransactionWrapper 我希望如果配置为使用 JTA,就像这篇文章中的情况一样: Spring + Eclipselink + JtaTransactionManager = javax.persistence.TransactionRequiredException

您可能想要验证正在使用的persistence.xml 是否标记为JTA,并且是您显示的那个,因为它可能是另一个persistence.xml 在您的类路径中被拾取。

于 2012-11-08T15:48:35.900 回答
2

当前没有交易处于活动状态?表示没有开始 entityTransacton

你能试一下吗

@Override
public void save(StoredObject storedObject) {
    entityManager.getTransaction().begin();
    entityManager.persist(storedObject);
    entityManager.flush(); // <---- throws Exception
}

但是为开始和提交保留一个单独的方法。

于 2012-11-05T09:24:20.407 回答
2

您不需要持久单元中的提供者吗?

于 2012-11-07T10:56:08.420 回答
2

根据 Spring 文档

<tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in. 
This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.

请验证,您已正确配置

于 2012-11-07T11:22:28.730 回答
2

根据Spring 文档,它对默认值的描述如下:

“tx:annotation-driven”元素上的“proxy-target-class”属性控制为使用@Transactional 注释注释的类创建什么类型的事务代理。如果 proxy-target-class 属性设置为 true,则创建基于类的代理。如果 proxy-target-class 为 false 或省略该属性,则创建基于标准 JDK 接口的代理。

由于您的案例是基于类的代理,因此您需要像这样添加此属性:

tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"

你甚至可以失去属性:

事务管理器="事务管理器"

因为它无论如何都是默认的......!

于 2012-11-09T00:22:08.767 回答
0

如果您使用 transaction-type="JTA" 那么在 web 容器 ex: Tomcat 中,您需要使用 JOTM 来管理事务并在 Tomcat 和 Spring 中配置它。

而且,在文件 persistence.xml 中,您需要添加以下行:

 <properties>

<property name="eclipselink.target-server" value="org.eclipse.persistence.transaction.jotm.JotmTransactionController"/>

</properties>
于 2015-12-04T07:11:25.793 回答