当前位置:   article > 正文

spring boot,JPA和Atomikos实现分布式事务_transaction manager not running

transaction manager not running

一、实例描述和实体模型

     我们想在同一时间两个不同的数据库保存两个实体,这个操作需要事务。因此,在这个例子中,我们有一个Customer实体,它将第一个持久化到数据库中,而Order实体将被持久化到第二个数据库中。这两个实体非常简单,这个实例仅仅是一个示范。

这个结果实现如下:值得注意的是,它是属于两个不同的包,原因有两点:

1、项目呈现上下级逻辑分离的

2、每一个repository将扫描包含实体的包,并且进行管理。

 

  1. package com.at.mul.domain.customer;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.GenerationType;
  6. import javax.persistence.Id;
  7. import javax.persistence.Table;
  8. import lombok.Data;
  9. import lombok.EqualsAndHashCode;
  10. @Entity
  11. @Table(name = "customer")
  12. @Data
  13. @EqualsAndHashCode(exclude = { "id" })
  14. public class Customer {
  15. @Id
  16. @GeneratedValue(strategy = GenerationType.AUTO)
  17. private Integer id;
  18. @Column(name = "name", nullable = false)
  19. private String name;
  20. @Column(name = "age", nullable = false)
  21. private Integer age;
  22. }
  1. package com.at.mul.domain.order;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.GenerationType;
  6. import javax.persistence.Id;
  7. import javax.persistence.Table;
  8. import lombok.Data;
  9. import lombok.EqualsAndHashCode;
  10. @Entity
  11. @Table(name = "orders")
  12. @Data
  13. @EqualsAndHashCode(exclude = { "id" })
  14. public class Order {
  15. @Id
  16. @GeneratedValue(strategy = GenerationType.AUTO)
  17. private Integer id;
  18. @Column(name = "code", nullable = false)
  19. private Integer code;
  20. @Column(name = "quantity", nullable = false)
  21. private Integer quantity;
  22. }

对于注解@Data和@EqualsAndHashCode请看Lombok

 

二、写repositories接口

在这个事例中它是一个标准,这里是需要注意的是我写了两个接口在两个不同的包,这个原因在下一个步骤将会解释:

  1. package com.at.mul.repository.customer;
  2. import org.springframework.data.jpa.repository.JpaRepository;
  3. import com.at.mul.domain.customer.Customer;
  4. public interface CustomerRepository extends JpaRepository<Customer, Integer> {
  5. }
  1. package com.at.mul.repository.order;
  2. import org.springframework.data.jpa.repository.JpaRepository;
  3. import com.at.mul.domain.order.Order;
  4. public interface OrderRepository extends JpaRepository<Order, Integer> {
  5. }

三、写配置类:

     这里有一点有兴趣的事,@DependsOn("transactionManager")注解不是强制的,但是在测试启动时我需要去掉若干的警告,像logs里面的WARNING: transaction manager not running?。下一个注解@EnableJpaRepositories才是重要的。

1、情况一是对于注解组件进行包扫描(repository接口),并且在我的实例中,我想仅仅repositories

customer (相反的就是repositories order)

2、情况二是实体管理者去管理实体,在我的实例中,customerEntityManager管理customer相关操作并且orderEntityManager管理order的相关操作

3、情况三是事务管理器被使用,在我的实例中transactionManager定义在MainConfig类中。这是需要对于每一个@EnableJpaRepositories 获取的工作事务都是同一个。

  1. package com.at.mul;
  2. import java.util.HashMap;
  3. import javax.sql.DataSource;
  4. import org.h2.jdbcx.JdbcDataSource;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.context.annotation.DependsOn;
  10. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  11. import org.springframework.orm.jpa.JpaVendorAdapter;
  12. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  13. import com.at.mul.repository.customer.CustomerDatasourceProperties;
  14. import com.atomikos.jdbc.AtomikosDataSourceBean;
  15. @Configuration
  16. @DependsOn("transactionManager")
  17. @EnableJpaRepositories(basePackages = "com.at.mul.repository.customer", entityManagerFactoryRef = "customerEntityManager", transactionManagerRef = "transactionManager")
  18. @EnableConfigurationProperties(CustomerDatasourceProperties.class)
  19. public class CustomerConfig {
  20. @Autowired
  21. private JpaVendorAdapter jpaVendorAdapter;
  22. @Autowired
  23. private CustomerDatasourceProperties customerDatasourceProperties;
  24. @Bean(name = "customerDataSource", initMethod = "init", destroyMethod = "close")
  25. public DataSource customerDataSource() {
  26. JdbcDataSource h2XaDataSource = new JdbcDataSource();
  27. h2XaDataSource.setURL(customerDatasourceProperties.getUrl());
  28. AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
  29. xaDataSource.setXaDataSource(h2XaDataSource);
  30. xaDataSource.setUniqueResourceName("xads1");
  31. return xaDataSource;
  32. }
  33. @Bean(name = "customerEntityManager")
  34. @DependsOn("transactionManager")
  35. public LocalContainerEntityManagerFactoryBean customerEntityManager() throws Throwable {
  36. HashMap<String, Object> properties = new HashMap<String, Object>();
  37. properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
  38. properties.put("javax.persistence.transactionType", "JTA");
  39. LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
  40. entityManager.setJtaDataSource(customerDataSource());
  41. entityManager.setJpaVendorAdapter(jpaVendorAdapter);
  42. entityManager.setPackagesToScan("com.at.mul.domain.customer");
  43. entityManager.setPersistenceUnitName("customerPersistenceUnit");
  44. entityManager.setJpaPropertyMap(properties);
  45. return entityManager;
  46. }
  47. }
  1. package com.at.mul;
  2. import java.util.HashMap;
  3. import javax.sql.DataSource;
  4. import org.h2.jdbcx.JdbcDataSource;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.context.annotation.DependsOn;
  10. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  11. import org.springframework.orm.jpa.JpaVendorAdapter;
  12. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  13. import com.at.mul.repository.order.OrderDatasourceProperties;
  14. import com.atomikos.jdbc.AtomikosDataSourceBean;
  15. @Configuration
  16. @DependsOn("transactionManager")
  17. @EnableJpaRepositories(basePackages = "com.at.mul.repository.order", entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager")
  18. @EnableConfigurationProperties(OrderDatasourceProperties.class)
  19. public class OrderConfig {
  20. @Autowired
  21. private JpaVendorAdapter jpaVendorAdapter;
  22. @Autowired
  23. private OrderDatasourceProperties orderDatasourceProperties;
  24. @Bean(name = "orderDataSource", initMethod = "init", destroyMethod = "close")
  25. public DataSource orderDataSource() {
  26. JdbcDataSource h2XaDataSource = new JdbcDataSource();
  27. h2XaDataSource.setURL(orderDatasourceProperties.getUrl());
  28. AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
  29. xaDataSource.setXaDataSource(h2XaDataSource);
  30. xaDataSource.setUniqueResourceName("xads2");
  31. return xaDataSource;
  32. }
  33. @Bean(name = "orderEntityManager")
  34. public LocalContainerEntityManagerFactoryBean orderEntityManager() throws Throwable {
  35. HashMap<String, Object> properties = new HashMap<String, Object>();
  36. properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
  37. properties.put("javax.persistence.transactionType", "JTA");
  38. LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
  39. entityManager.setJtaDataSource(orderDataSource());
  40. entityManager.setJpaVendorAdapter(jpaVendorAdapter);
  41. entityManager.setPackagesToScan("com.at.mul.domain.order");
  42. entityManager.setPersistenceUnitName("orderPersistenceUnit");
  43. entityManager.setJpaPropertyMap(properties);
  44. return entityManager;
  45. }
  46. }

另一个重要的事,这里LocalContainerEntityManagerFactoryBean的定义:

1、@bean注解有获取一个name,他是在@EnableJpaRepositories注解中进行指定的。

2、你需要设置一些属性到JpaPropertyMap中,详细的说,你需要标注transaction是JTA和JTA平台是AtomikosJtaPlatform.class.getName()

我的实例不能正常执行的就是我为什么不设置第二个属性的原因。Dave Syer写道"我看了Atomikos范围之外Hibernate4不能工作",因此你需要实现类去设置hibernate.transaction.jta.platform属性,依我看来,这不是一个很好的文档,但是庆幸Oliver Gierke发现了另一个关于这个标题的文章 StackOverflow discussion 。如果你是用的是另一个JTA提供者,这个可能对你有用this useful.

四、写一个AbstractJtaPlatform实现

注意:文章到这里还没有完,由于篇幅限制,完整内容请到hongfu951博客上查看

完整内容URL地址用多数据库spring boot,spring data JPA和Atomikos实现分布式事务

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/346904
推荐阅读
相关标签
  

闽ICP备14008679号