【问题标题】:Using Spring @Transactional propagations in JTA在 JTA 中使用 Spring @Transactional 传播
【发布时间】:2014-02-04 08:22:36
【问题描述】:

由于我们的系统架构,我正在尝试实施客户端编排策略(ibm-client-orchestration)。我们使用一个集成层,它实际上编排了一些 Web 服务。对 Web 服务的调用是在单个工作单元中进行的,并委托给使用 Spring 框架的业务层。一个例子是这样的:

UserTransaction ut = getUserTransaction()
ut.begin();
// insert data, will be delegated to some jpa repository
service1.saveData(data)
// find data inserted above
service2.findData(data)
ut.commit();

在提到的链接中,作者建议在保存时使用传播 MANDATORY 并在查找时使用传播支持,这将尝试在事务日志中查找数据。不知何故,我不知道在上述情况下我无法在查找步骤中找到插入的数据。以下是一些可能会有所帮助的有用信息:

  1. 我们使用 Websphere 8.5。我们的数据源来自 Websphere,配置为 XA 数据源,取自 JNDI。
  2. Spring 的平台事务管理器配置为 JtaTransactionManager
  3. Entity Manger Factory 取自 LocalContainerEntityManagerFactoryBean 并使用具有以下属性的 Hibernate JPA Vendor:

    jpaProperties.setProperty("hibernate.hbm2ddl.auto", environment.getRequiredProperty("entitymanagerfactory.hibernate.hbm2ddl.production")); jpaProperties.setProperty("hibernate.connection.autocommit", "false"); jpaProperties.setProperty("hibernate.transaction.jta.platform", "org.hibernate.service.jta.platform.internal.WebSphereJtaPlatform"); jpaProperties.setProperty("hibernate.transaction.manager_lookup_class", "org.hibernate.transaction.WebSphereExtendedJTATransactionLookup");

  4. 我没有在 Websphere 中配置任何 JPA Provider,所以它应该是它的默认实现。

我提到如果我在委托 DAO 层中使用 jpa 存储库中的 saveAndFlush() 方法,我可以找到是否,但我宁愿不使用它并使用事务传播。

transactionManager bean 的定义:

    @Bean
public PlatformTransactionManager transactionManager() {
    JtaTransactionManager txManager = new JtaTransactionManager();
    txManager.afterPropertiesSet();
    return txManager;
}
    @Bean
public EntityManagerFactory entityManagerFactory() {
    // hibernate vendor
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setDatabase(databaseType());
    vendorAdapter.setGenerateDdl(true);

    // compose entityManager

    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setJpaVendorAdapter(vendorAdapter);
    factoryBean.setDataSource(datasource());
    factoryBean.setJtaDataSource(datasource());
    // scan packages
    factoryBean.setPackagesToScan(environment.getRequiredProperty("entitymanager.scan.packages"));

    // JPA properties
    factoryBean.setJpaProperties(getEntityManagerFactoryJpaProperties());

    factoryBean.afterPropertiesSet();

    return factoryBean.getObject();
}

感谢任何建议。 谢谢。

【问题讨论】:

  • 你应该由 spring 处理生命周期,你不应该自己打电话给afterPropertiesSet,spring 会为你做这件事。与getObject() 相同,您应该简单地返回FactoryBean 以便spring 可以正确管理它。

标签: spring jpa websphere jta


【解决方案1】:

对于初学者,您应该使用 websphre 特定的 JtaTransactionManager 而不是通用的。我建议将tag which detects which specific or generic one to use. So basically replace your definition of theJtaTransactionManager` 与以下内容一起使用:

<tx:jta-transaction-manager />

接下来,您的代码不使用 springs 事务管理,而是普通 JTA 事务要么使用注释来驱动事务(@Transactional&lt;tx:annotation-driven /&gt;,要么使用注入的 PlatformTransactionManager 来启动和提交事务。

TransactionStatus txStatus = getTransactionManager().getTransaction(null);
// insert data, will be delegated to some jpa repository
service1.saveData(data)
// find data inserted above
service2.findData(data)
getTransactionManager().commit(txStatus);

另请参阅the reference guide,了解另一种方法和更多信息。

LocalContainerEntityManagerFactoryBean 中确保注入jtaDataSource 属性而不是dataSource 属性,这将触发一些额外的设置。

@Bean
public FactoryBean<EntityManagerFactory> entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean();
    lcemfb.setJtaDataSource(dataSource());
    // .... Other properties
    return lcemfb;
}

关于您的休眠配置的另一个注意事项,hibernate.connection.* 属性由于数据源的注入而无用,并且您不需要 hibernate.transaction.manager_lookup_class,因为它(或至少应该)已被配置的 @ 覆盖987654335@.

【讨论】:

  • 我添加了一条关于它如何配置 transactionManager 和 entityManagerFactory 的评论。我会说这和你提到的一样。我不确定我们是否有可能在我们的集成层中获得事务管理器,因为该层与 Spring 框架无关。感谢您的回答。我会尝试,也许是一种服务定位器方法来从春天获取事务管理器。如果您有其他想法..
  • 不,不是..您使用的是JtaTransactionManager,而不是特定于 websphere 的。命名空间检测要使用的版本。此外,您的 LocalContainerEntityManagerFactoryBean 配置错误,您应该设置 dataSourcejtaDataSource 属性,而不是同时设置两者。关于事务管理器,我的印象是代码是由 Spring 管理的,如果不忽略那部分的话。
猜你喜欢
  • 2014-12-24
  • 2018-05-14
  • 2010-12-09
  • 2012-01-19
  • 2015-07-24
  • 1970-01-01
  • 2017-06-11
  • 2012-05-17
  • 2017-01-18
相关资源
最近更新 更多