2015-08-23 34 views
0

我在我的代码中使用了两个事务管理器。一个被标记为主要的。完整的配置使用Spring注释。
我尝试使用NON-primary事务管理器进行更新的表不能将数据保存在数据库中。如果我将同一个事务管理器标记为主,那么它会开始将数据插入到数据库中。Spring JPA存储库不能与两个事务管理器一起工作

在非主事务的情况下,我得到以下错误

org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress 
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:413) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:157) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy39.flush(Unknown Source) 
    at com.ashish.business.CreditCardManagementImpl.addCreditCardUser(CreditCardManagementImpl.java:44) 
    at com.ashish.business.CreditCardManagementImpl.addCrCardCustomerData(CreditCardManagementImpl.java:30) 

我的代码出现在以下位置 https://github.com/ashismo/repositoryForMyBlog/tree/master/spring/SpringJPARepoDistributedTransaction

在我的代码,com.ashish.appConfig包有三个类叫做AppConfig.java,CreditCardTransactionConfig.java和DebitCardTransactionConfig.java。凡的AppConfig包括了其他两个阶级,CreditCardTransactionConfig.java主事务管理器配置

我正在从JUnit的文件中的代码。并且上面提到的错误一旦我尝试做creditUserDetailRepository.flush();。如果我的代码中没有这行代码,那么我没有收到任何错误,但是数据没有被插入到表中。

有人可以帮我吗?

回答

0

在您的DebitCardTransactionConfig类中,您已使用@Primary注释标注debitEntityManagerFactory方法。该注释意味着,只要存在多个基于类型的自动装配候选项,就应该使用此实例。您所创建的PlatformTransactionManager就像这样:

@Bean(name="creditTransactionManager") 
@Qualifier("creditTransactionManager") 
public PlatformTransactionManager creditTransactionManager(
      EntityManagerFactory emf) { 
    //... 
} 

这意味着,春季应自动选择EntityManagerFactory。因此,这两个交易经理都被交给了借方实体经理工厂。

你应该速战速决做什么,是改变creditTransactionManager这样的声明:

@Bean(name="creditTransactionManager") 
@Qualifier("creditTransactionManager") 
// @Primary 
public PlatformTransactionManager creditTransactionManager() { 
    JpaTransactionManager transactionManager = new JpaTransactionManager(); 
    transactionManager.setEntityManagerFactory(creditEntityManagerFactory().getObject()); 
    return transactionManager; 
} 

作为一个@Configuration类调​​用不同@Bean方法是指从范围检索实例,这应该工作没有问题。不幸的是,我无法对此进行测试。请参阅旁注。

边注意事项 下面是关于您的代码的一些关于外观的注释。

  • 你的CreditCardTransactionConfigDebitCardTransactionConfig类非常类似。考虑提取一个可以消除大部分样板的超类。
  • bean名称取自@Bean带注释的方法的名称。您无需在@Bean@Qualifier注释中指定它。
  • 尽管共享存储库是一个好主意,以便任何人都可以克隆您的代码并对其进行测试,但我无法运行您的测试,因为它需要MySQL数据库。考虑使用像H2这样的内存数据库进行实验。
+0

非常感谢Apokralipsa。它为我工作。也感谢您的建议。我将在我的github代码中执行相同的操作。 我想和你一起检查一下(如你方的注释中的第二点),即如果我没有使用任何限定符,那么我的存储库将如何知道要使用哪个事务管理器和实体管理器? –

+0

您使用'@ EnableJpaRepositories'为位于特定包中的实体指定实体管理器工厂和事务管理器,它仍然可以这样工作。使用'@ Bean'注解的方法名称,该注释的name属性以及'@ Qualifier'注解的value属性在您的情况下具有相同的用途,因此您只需设置相同的名称三次。 – Apokralipsa

相关问题