Cheetahcubs 2020-01-03
场景描述:
业务系统中存在针对用户对一些特定字段(如:身份证、银行卡号)的操作,需要进行日志记录及入库日志。项目架构是基于boot为基石的SpringCloud分布式架构,业务模块暂时称呼为模块A,日志记录属于公共模块暂时称呼为模块B。模块A操作步骤成功之后,会调用模块B进行日志记录。
名词解释:
数据库事务的ACID (原子性、一致性、隔离性、持久性),分布式事务的BASE理论(分布式事务要求实现最终一致性)。
实现核心技术:
Jta+atomikos
jta:java中对事务处理的api
atomikos:为Java平台提供增值服务的并且开源类事务管理器
实现步骤:
1、在pom文件文件中添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency>
2、在application.properties中配置两个数据源的
spring: datasource: # 数据库1 db1: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource jdbc-url: jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&allowMultiQueries=true username: root password: newpwd # 数据库2 db2: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource jdbc-url: jdbc:mysql://localhost:3306/test2?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&allowMultiQueries=true username: root password: newpwd # 分布式锁 jta: # log-dir: classpath*:tx-logs transaction-manager-id: txManager
3、添加conf配置类:
@Data @ConfigurationProperties(prefix = "spring.datasource.db1") public class DB1Config { @Value("${spring.datasource.db1.jdbc-url}") private String url_jdbc; @Value("${spring.datasource.db1.username}") private String username; @Value("${spring.datasource.db1.password}") private String password; }
4、添加数据源类:
@Configuration @MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory") public class DB1DataSourcesConfig { @Primary @Bean(name = "db1DataSource") public DataSource dataSource(DB1Config DB1Config) { MysqlXADataSource mysqlXADataSource = new MysqlXADataSource(); mysqlXADataSource.setUrl(DB1Config.getUrl_jdbc()); mysqlXADataSource.setUser(DB1Config.getUsername()); mysqlXADataSource.setPassword(DB1Config.getPassword()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean(); atomikosDataSourceBean.setXaDataSource(mysqlXADataSource); atomikosDataSourceBean.setUniqueResourceName("db1DataSource"); return atomikosDataSourceBean; } @Primary @Bean(name = "db1SqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSource); sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/db1/*.xml")); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); sessionFactoryBean.setConfiguration(configuration); return sessionFactoryBean.getObject(); } @Primary @Bean(name = "db1SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
5、添加db2的配置类和数据源类,差别与db1的地方在于:db1是默认的数据源,有@Primary注解,db2的不需要。
6、在启动类上添加注解,指定扫描路径:
@EnableConfigurationProperties(value = {DB2Config.class, DB1Config.class})
7、在要进行事务控制的方法上添加@Transaction注解,通过调用dao层的方法,实现对数据库的操作。(此处可以用jpa或者mybatis)
总结:
SpringBoot 通过在启动时加载不同的数据源,并将不同的数据源注入到不同的 repository 包下,从而实现项目多数据源操作,在项目中使用多数据源时,需要用到哪个数据源,只需要将对应包下的 repository 注入操作即可。