在JTA中使用Spring @Transactional传播

时间:2014-02-04 08:22:36

标签: spring jpa websphere jta

由于我们的系统架构,我正在尝试实施客户端编排策略(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();

在上面提到的链接中,作者建议在查找时使用传播强制保存和传播SUPPORTS,它将尝试在事务日志中查找数据。不知何故,我不知道在给定上述场景的情况下,我无法在查找步骤中找到插入的数据。以下是一些可能有用的有用信息:

  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,所以应该是它的默认实现。

  5. 我提到如果我在委托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();
    }
    

    任何建议都表示赞赏。 感谢。

1 个答案:

答案 0 :(得分:0)

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

<tx:jta-transaction-manager />

接下来,您的代码不使用spring事务管理,但是普通JTA事务使用注释来驱动事务(@Transactional<tx:annotation-driven />或使用注入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配置的另一个注意事项,hibernate.connection.*属性由于数据源的注入而无用,你不需要hibernate.transaction.manager_lookup_class因为(或者至少应该)已经覆盖按配置的JtaPlatform