繁体   English   中英

TransactionRequiredException:Spring Data JPA正在进行任何事务

[英]TransactionRequiredException: no transaction is in progress with Spring Data JPA

看了看 周围类似的问题,但找不到一个解决方案:

我有一个Spring Data JPA应用程序,每当我尝试进行javax.persistence.TransactionRequiredException: no transaction is in progress时,都会得到javax.persistence.TransactionRequiredException: no transaction is in progress

我认为这与“事务管理器”或“实体管理器工厂”有关,但我不能指责。

上下文文件在这里 (最新签入在这里 ),但这是重要的部分:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSourceMySQL" />
    <property name="persistenceUnitName" value="spring-jpa" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="generateDdl" value="true" />
            <property name="showSql" value="true" />
            <property name="database" value="MYSQL" />
        </bean>
    </property>
</bean>

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

<bean id="dataSourceMySQL" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/dbname"/>
    <property name="username" value="user"/>
    <property name="password" value="pass"/>
</bean>

<jpa:repositories base-package="com.simplecash.dal.repository" />

一个样品库的位置 ,然后创建一个存储库厂在这里 ,这我不知道,如果我需要......然后使用它在这里 (第34行)。

public void populateWithTestData() {

    Bank bank = new Bank();
    bank.setName("ContentName");
    bank.setCode("ContentCode");

    RepositoryFactory.getEntityManager().getTransaction().begin();
    BankRepository bankRepository = RepositoryFactory.getRepository(BankRepository.class);
    bankRepository.save(bank);
    bankRepository.flush();
    RepositoryFactory.getEntityManager().getTransaction().commit();
}

上面有几件事是错误的,但是我已经尝试修复它,但是不能:

  1. 开始和提交事务是显式的。
  2. bankRepository应该是@Autowired ,但是当我这样做时,我得到null 但是,在此测试用例中,它是自动装配的并且可以工作。

有没有人遇到过类似的问题,知道发生了什么事? 非常感谢您抽出宝贵的时间阅读本文。 希望这个问题的答案能对其他人有所帮助。

此处提供的两个答案都很好(使用注入来获取代理Bean和使用事务注释),但是,我很确定要使注释驱动的事务(@Transactional)正常工作,您需要在以下代码中添加以下内容:您的xml配置:

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

还要确保在您的bean-tag中添加tx-namespace:

<beans
  <!-- SNIP, other namespaces -->
xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="
  <!-- SNIP, other locations -->
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

spring-batchspring-jpa结合使用时,我遇到了类似的问题。 在我的批处理XML中,我有这一行:

<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>

由于JPA需要PlatformTransactionManager ,因此导致了错误。

  • 开始和提交事务是显式的。

Spring对您的存储库bean(例如BankRepository )进行的操作是,围绕它创建一个代理,然后准备将其注入其他协作者(在您的情况下为DatabaseManagerDAO 但是,如果您自己创建对象,就像这样做:

BankRepository bankRepository = RepositoryFactory.getRepository(BankRepository.class);

代替了预期的Spring代理(已经为您完成事务管理),您得到的是一个简单的对象,除了立即声明之外,它什么都不知道。

相反,您需要做的就是信任Spring为您做管道工作,只需将bankRepository bean注入DatabaseManagerDAO (尽管我并不认为您同时需要DAO和Repository,因为这些术语实际上是同一回事:)

  • 这里的存储库工厂,我不确定是否需要...

无需其他抽象。 只需将其作为bean注入到任何需要它的组件中即可。

  • bankRepository应该是@Autowired ,但是当我这样做时,我得到null 但是,在此测试用例中,它是自动装配的并且可以工作。

在一个情况下, 它的工作原理您用您的测试AbstractTransactionalJUnit4SpringContextTests ,它知道 “bankRepository”豆,因此autowires它。 在您的DatabaseManagerDAO ,我看不到bankRepository自动装配和设置bankRepository ,实际上,您是在工厂手动创建的。

编辑以回答评论

XML配置中的jpa:repositories真正执行的操作=>它扫描软件包,并为每个组件(分别标为@Repository或实现Repository接口)创建Spring Bean。

考虑到这一点,要在DatabaseManagerDAO使用BankRepository存储库,应该做的就是注入它。 您可以通过“自动装配”来实现:

@Service
public class DatabaseManagerDAO {

    @Autowired
    BankRepository bankRepository;
    ... 
}

而不是通过工厂手动创建它。

同样,在您的情况下, DatabaseManagerDAO可能是服务( @Service ),而不是DAO ,但是我将由您自己决定。

请注意,为了使自动装配正常工作,Spring还应该加载DatabaseManagerDAO ,因此在打包对其进行扫描时,请确保它具有Spring批注之一( @Service / @Component )(例如, <context:component-scan base-package="org.example"/> )。

我认为在您的设置中,事务由JTA管理,因此您不能显式启动/停止它们(即em.getTransaction()。begin()将不起作用)。 尝试通过注解告诉Spring您希望某种方法成为(JTA管理的)事务的一部分,例如:

@Transactional
public void populateWithTestData() {
   //...    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM