一、实例描述和实体模型
我们想在同一时间两个不同的数据库保存两个实体,这个操作需要事务。因此,在这个例子中,我们有一个Customer实体,它将第一个持久化到数据库中,而Order实体将被持久化到第二个数据库中。这两个实体非常简单,这个实例仅仅是一个示范。
这个结果实现如下:值得注意的是,它是属于两个不同的包,原因有两点:
1、项目呈现上下级逻辑分离的
2、每一个repository将扫描包含实体的包,并且进行管理。
package com.at.mul.domain.customer;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Entity
@Table(name = "customer")
@Data
@EqualsAndHashCode(exclude = { "id" })
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "age", nullable = false)
private Integer age;
}
package com.at.mul.domain.order;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Entity
@Table(name = "orders")
@Data
@EqualsAndHashCode(exclude = { "id" })
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "code", nullable = false)
private Integer code;
@Column(name = "quantity", nullable = false)
private Integer quantity;
}
对于注解@Data和@EqualsAndHashCode请看Lombok
二、写repositories接口
在这个事例中它是一个标准,这里是需要注意的是我写了两个接口在两个不同的包,这个原因在下一个步骤将会解释:
package com.at.mul.repository.customer;
import org.springframework.data.jpa.repository.JpaRepository;
import com.at.mul.domain.customer.Customer;
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
}
package com.at.mul.repository.order;
import org.springframework.data.jpa.repository.JpaRepository;
import com.at.mul.domain.order.Order;
public interface OrderRepository extends JpaRepository<Order, Integer> {
}
三、写配置类:
这里有一点有兴趣的事,@DependsOn("transactionManager")注解不是强制的,但是在测试启动时我需要去掉若干的警告,像logs里面的WARNING: transaction manager not running?。下一个注解@EnableJpaRepositories才是重要的。
1、情况一是对于注解组件进行包扫描(repository接口),并且在我的实例中,我想仅仅repositories
customer (相反的就是repositories order)
2、情况二是实体管理者去管理实体,在我的实例中,customerEntityManager管理customer相关操作并且orderEntityManager管理order的相关操作
3、情况三是事务管理器被使用,在我的实例中transactionManager定义在MainConfig类中。这是需要对于每一个@EnableJpaRepositories 获取的工作事务都是同一个。
package com.at.mul;
import java.util.HashMap;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import com.at.mul.repository.customer.CustomerDatasourceProperties;
import com.atomikos.jdbc.AtomikosDataSourceBean;
@Configuration
@DependsOn("transactionManager")
@EnableJpaRepositories(basePackages = "com.at.mul.repository.customer", entityManagerFactoryRef = "customerEntityManager", transactionManagerRef = "transactionManager")
@EnableConfigurationProperties(CustomerDatasourceProperties.class)
public class CustomerConfig {
@Autowired
private JpaVendorAdapter jpaVendorAdapter;
@Autowired
private CustomerDatasourceProperties customerDatasourceProperties;
@Bean(name = "customerDataSource", initMethod = "init", destroyMethod = "close")
public DataSource customerDataSource() {
JdbcDataSource h2XaDataSource = new JdbcDataSource();
h2XaDataSource.setURL(customerDatasourceProperties.getUrl());
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(h2XaDataSource);
xaDataSource.setUniqueResourceName("xads1");
return xaDataSource;
}
@Bean(name = "customerEntityManager")
@DependsOn("transactionManager")
public LocalContainerEntityManagerFactoryBean customerEntityManager() throws Throwable {
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setJtaDataSource(customerDataSource());
entityManager.setJpaVendorAdapter(jpaVendorAdapter);
entityManager.setPackagesToScan("com.at.mul.domain.customer");
entityManager.setPersistenceUnitName("customerPersistenceUnit");
entityManager.setJpaPropertyMap(properties);
return entityManager;
}
}
package com.at.mul;
import java.util.HashMap;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import com.at.mul.repository.order.OrderDatasourceProperties;
import com.atomikos.jdbc.AtomikosDataSourceBean;
@Configuration
@DependsOn("transactionManager")
@EnableJpaRepositories(basePackages = "com.at.mul.repository.order", entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager")
@EnableConfigurationProperties(OrderDatasourceProperties.class)
public class OrderConfig {
@Autowired
private JpaVendorAdapter jpaVendorAdapter;
@Autowired
private OrderDatasourceProperties orderDatasourceProperties;
@Bean(name = "orderDataSource", initMethod = "init", destroyMethod = "close")
public DataSource orderDataSource() {
JdbcDataSource h2XaDataSource = new JdbcDataSource();
h2XaDataSource.setURL(orderDatasourceProperties.getUrl());
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(h2XaDataSource);
xaDataSource.setUniqueResourceName("xads2");
return xaDataSource;
}
@Bean(name = "orderEntityManager")
public LocalContainerEntityManagerFactoryBean orderEntityManager() throws Throwable {
HashMap<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setJtaDataSource(orderDataSource());
entityManager.setJpaVendorAdapter(jpaVendorAdapter);
entityManager.setPackagesToScan("com.at.mul.domain.order");
entityManager.setPersistenceUnitName("orderPersistenceUnit");
entityManager.setJpaPropertyMap(properties);
return entityManager;
}
}
另一个重要的事,这里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.
注意:文章到这里还没有完,由于篇幅限制,完整内容请到hongfu951博客上查看
完整内容URL地址:用多数据库spring boot,spring data JPA和Atomikos实现分布式事务
相关推荐
spring 3.2+ jpa 1.1+ atomikos3.9 配置mysql+sqlserver2000多数据源 包含所需所有jar包,完整项目
springboot-jpa hibernate,mybatis +atomikos 多数据库事务管理 springboot2.05版本,该项目实现mybatis,hibernate多数据源事务的控制
myeclipse开发,导入即可用,可以参阅http://www.cnblogs.com/shamo89/p/7326718.html
#boot-jpa-security-dmdb-freemark spring boot spring security 达梦数据库 ftl assembly 打包
该项目是一个基于Spring Boot 2.1.0、Spring Boot Jpa、Spring Security、Redis的前后端分离后台管理系统,权限控制采用RBAC,菜单采用动态路由,适合用于个人学习和实践Vue和Spring Boot的开发技术。
springboot+Atomikos+jpa+mysql的JTA分布式事务实现,本案例涉及到2个数据库,预期结果,在同一个事务中,两个库的状态一致
Spring Boot Jpa 自定义实现Hibernate注释注解
Spring Boot+Jpa多数据源配置Demo,可同时支持多种数据库,不同数据库,同时支持不同数据库的JdbcTemplate
Spring Boot 集成 JPASpring Boot 集成 JPASpring Boot 集成 JPASpring Boot 集成 JPASpring Boot 集成 JPASpring Boot 集成 JPA
Spring Data JPA API。 Spring Data JPA 开发文档。 官网 Spring Data JPA API。
Spring Boot+Maven+Spring Data JPA+apache Shiro+Easyui实现通用用户权限管理系统
项目描述 企业的销售要进行培训,由技术人员进行辅导并考评检测培训效果,所以有了这个小系统。实现了系统的登录验证、请求拦截验证、基础...springboot + spring data jpa + layui http://localhost/ zuidaima 111111
eladmin前端源码,项目基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 Spring Security、Redis、Vue的前后端分离后台管理系统, 权限控制采用 RBAC,菜单动态路由
eladmin jpa版本:前端源码,项目基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 Spring Security、Redis、Vue的前后端分离后台管理系统.zip
Spring Boot+Spring Data Jpa进...本系统使用Spring Boot架构,数据访问层采用Spring Data Jpa,安全框架采用Shiro,实现了完整权限系统,Controller方法采用Shiro注解,来实现有效的权限控制;界面采用了EasyUI技术。
主要介绍了Spring boot jpa 删除数据和事务管理的问题实例详解,涉及业务场景的一些知识和遇到的的问题,需要的朋友可以参考。
5-Spring-Boot(五):spring data jpa的使用.docx5-Spring-Boot(五):spring data jpa的使用.docx5-Spring-Boot(五):spring data jpa的使用.docx5-Spring-Boot(五):spring data jpa的使用.docx5-Spring-Boot(五):...
一健开发部署,api接口+mysql数据库,spring-boot-jpa
Spring Data JPA中文文档1.4.3
内容概要:这个毕业设计项目基于Spring Boot框架、Spring Data JPA和Thymeleaf模板引擎,旨在设计和实现一个旅游网站。该网站提供了旅游线路的展示、用户预订、订单管理等功能,以帮助用户方便地选择和预订旅游线路...