【问题标题】:Why is my transaction not active? javax.persistence.TransactionRequiredException: Executing an update/delete query为什么我的交易不活跃? javax.persistence.TransactionRequiredException:执行更新/删除查询
【发布时间】:2012-06-16 11:49:35
【问题描述】:

我有一个 Spring Web Service (Spring-WS) 应用程序,我正在尝试配置它以使用它。我正在使用的堆栈如下

Spring 3
Spring-WS
JPA with Hibernate as the provider
JBoss 7.1*

应用配置如下:

persistence.xml

<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/myDataSource</jta-data-source>
        <non-jta-data-source>java:jboss/datasources/myDataSource</non-jta-data-source>
        <class>myPackage.MyClass</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>           
            <property name="hibernate.connection.autocommit" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="validate"/>
            <property name="hibernate.show_sql" value="false"/>
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
            <property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider"/>
            <property name="hibernate.search.default.indexBase" value="./lucene/indexes"/>
            <property name="hibernate.search.default.batch.merge_factor" value="10"/>
            <property name="hibernate.search.default.batch.max_buffered_docs" value="10"/>
        </properties>
    </persistence-unit>

spring.xml - 实体管理器和事务管理器

<context:annotation-config/>

    <context:component-scan base-package="com.mypackage"/>

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <!-- Live database entity and transaction managers -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:dataSource-ref="myDataSource">

        <property name="persistenceUnitName" value="myPersistenceUnit" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref="entityManagerFactory" />

    <tx:annotation-driven transaction-manager="transactionManager" />           

Web.xml - 加载上面的 spring.xml 文件

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/app-config.xml
            /WEB-INF/spring.xml
            /WEB-INF/spring-datasources.xml
         </param-value>   
     </context-param>

spring-datasources.xml

<jee:jndi-lookup id="myDataSource" jndi-name="java:jboss/datasources/myDataSource"/>

在我的 DAO 类中,我对 entityManager 有以下定义。

@PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit")
protected EntityManager entityManager;

@Transactional
    public void updateProduct(Product product) {

        //  Save the document to the database
        update(product);
    }

上面的更新方法只是调用了一个泛型方法,调用entityManager.merge(object);

现在,当我测试上述内容时,我发现如果我从数据库中读取它可以工作,但如果我正在写入数据库(即创建或更新)它就不起作用。 如果我尝试写信给我会得到以下异常:

javax.persistence.TransactionRequiredException: Executing an update/delete query
   at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
   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$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310)
   at $Proxy96.executeUpdate(Unknown Source)

我猜测我可以从数据库中读取数据,这意味着事务管理器的配置有问题。有什么想法吗?

编辑

好的,我刚刚重新阅读了上面的内容,发现最后一点有点错误。我上面显示的异常只有在我使用 JPQL 使用entityManager.createQuery 发出更新语句时才会发生。如果我尝试使用entityManager.merge() 更新实体,实际上什么都不会发生。不返回异常但不更新行。

【问题讨论】:

  • 也许是个愚蠢的问题,但你怎么称呼updadeProduct?是接口吗?

标签: java spring hibernate jboss hibernate-search


【解决方案1】:

当您将方法标记为 @Transactional 时,您指望 JTA,但是 - 正如 altanis 所述 - 但您将持久性单元的事务类型定义为 RESOURCE_LOCAL 而非 JTA。

1) 如果您想使用容器管理的事务然后更改事务类型,将您的数据源定义为 JBoss 中的 JTA 数据源,并将 non-jta-data-source 更改为 jta-data-source

2) 如果您想管理自己的事务,请保持 persistence.xml 和数据源定义不变,但在任何持久化、合并、删除操作之前通过调用 entitymanager.getTransaction().begin() 和在业务单元结束时,调用 entitymanager.getTransaction().commit() 或 entitymanager.getTransaction().rollback()。在这种情况下,由于您自己管理事务,因此在 updateProduct() 中使用 @Transactional 启动 JTA 事务似乎没有意义。

【讨论】:

    【解决方案2】:

    尝试在 persistence.xml 中将 transaction-type="RESOURCE_LOCAL" 更改为 transaction-type="JTA"。此外,您可能需要从 persistence.xml 中删除元素。

    【讨论】:

    • 我没有在 Jboss 中配置 JTA 数据源。需要删除哪个元素?
    • 我正在考虑删除“non-jta-data-source”。我注意到您的数据源用于“non-jta-data-source”以及“jta-data-source”。这就是我提到将“事​​务类型”更改为 JTA 的原因。
    猜你喜欢
    • 2013-04-18
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2023-01-30
    • 2021-02-12
    相关资源
    最近更新 更多