1.pom文件
com.atomikos transactions 4.0.6 com.atomikos transactions-api 4.0.6 com.atomikos transactions-jta 4.0.6 com.atomikos transactions-jdbc 4.0.6 com.atomikos atomikos-util 4.0.6 javax.transaction javax.transaction-api 1.2
2. aplication.properties
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.url=jdbc:mysql:///test2?useUnicode=true&useSSL=false&characterEncoding=utf8 spring.datasource.username=xxxx spring.datasource.password=xxxxx spring.datasource.driver-class-name=com.mysql.jdbc.Driver #ds1,ds2 其他两个数据源 slave.datasource.names=ds1,ds2 #ds1 slave.datasource.ds1.driver=com.mysql.jdbc.Driver slave.datasource.ds1.url=jdbc:mysql:///lottery?useUnicode=true&useSSL=false&characterEncoding=utf8 slave.datasource.ds1.username=xxxxx slave.datasource.ds1.password=xxxxx #ds2 slave.datasource.ds2.driver=com.mysql.jdbc.Driver slave.datasource.ds2.url=jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8 slave.datasource.ds2.username=root slave.datasource.ds2.password=root
3.DbConfig 实体类
import java.io.Serializable; @Data public class DbConfig implements Serializable{ private static final long serialVersionUID = 1L; private String url; private String username; private String password; }
4. 配置数据源 DataSourceConfig 链接主库
package com.spf.boot.atomikos.db; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import javax.sql.DataSource; /** * atomikos 分布式数据源 */ @Configuration @MapperScan(basePackages = {"com.spf.boot.mapper.ds"}, sqlSessionTemplateRef = "masterSqlSessionTemplate") public class DataSourceConfig { @Bean("dbConfig") @ConfigurationProperties(prefix = "spring.datasource") public DbConfig getDbConfig() { return new DbConfig(); } //************************************************************************************************************************************************** //配置数据源 @Primary @Bean(name="datasource") public DataSource Datasource(@Qualifier("dbConfig") DbConfig config1) { MysqlXADataSource mysqlXADataSource=new MysqlXADataSource(); mysqlXADataSource.setUrl(config1.getUrl()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXADataSource.setPassword(config1.getPassword()); mysqlXADataSource.setUser(config1.getUsername()); AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean(); atomikosDataSourceBean.setXaDataSource(mysqlXADataSource); atomikosDataSourceBean.setUniqueResourceName("datasource"); // atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize()); // atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize()); // atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime()); // atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout()); // atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout()); // atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval()); // atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime()); return atomikosDataSourceBean; } //************************************************************************************************************************************************** // @Bean(name="primaryJdbcTemplate") // public JdbcTemplate primaryJdbcTemplate(@Qualifier("datasource")DataSource dataSource) { // return new JdbcTemplate(dataSource); // } @Bean(name = "sqlSessionFactory") @Primary public SqlSessionFactory sqlSessionFactory(@Qualifier("datasource")DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); //添加XML目录 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml")); return sqlSessionFactoryBean.getObject(); } @Bean(name = "masterSqlSessionTemplate") @Primary public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
5. 配置从库数据链接 DataDs1Source
package com.spf.boot.atomikos.db; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; import java.io.IOException; /** * @author ShuPF * @类说明: * @date 2018-12-27 14:42 */ @Configuration @MapperScan(basePackages = {"com.spf.boot.mapper.ds1"}, sqlSessionTemplateRef = "ds1SqlSessionTemplate") public class DataDs1Source { @Bean("db1Config") @ConfigurationProperties(prefix = "slave.datasource.ds1") public DbConfig getDb2Config() { return new DbConfig(); } //配置数据源 @Bean(name="datasourceDs1") public DataSource datasourceDs1(@Qualifier("db1Config") DbConfig config1) { MysqlXADataSource mysqlXADataSource=new MysqlXADataSource(); mysqlXADataSource.setUrl(config1.getUrl()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXADataSource.setPassword(config1.getPassword()); mysqlXADataSource.setUser(config1.getUsername()); AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean(); atomikosDataSourceBean.setXaDataSource(mysqlXADataSource); atomikosDataSourceBean.setUniqueResourceName("datasourceDs1"); // atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize()); // atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize()); // atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime()); // atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout()); // atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout()); // atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval()); // atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime()); return atomikosDataSourceBean; } // @Bean(name="ds1JdbcTemplate") // public JdbcTemplate ds1JdbcTemplate(@Qualifier("datasourceDs1")DataSource dataSource) { // return new JdbcTemplate(dataSource); // } @Bean(name = "ds1SqlSessionFactory") public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("datasourceDs1")DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); //添加XML目录 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml")); return sqlSessionFactoryBean.getObject(); } @Bean(name = "ds1SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("ds1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
6. DataDs2Source
package com.spf.boot.atomikos.db; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; /** * @author ShuPF * @类说明: * @date 2018-12-27 14:42 */ @Configuration @MapperScan(basePackages = {"com.spf.boot.mapper.ds2"}, sqlSessionTemplateRef = "ds2SqlSessionTemplate") public class DataDs2Source { @Bean("db2Config") @ConfigurationProperties(prefix = "slave.datasource.ds2") public DbConfig getDb3Config() { return new DbConfig(); } //配置数据源 @Bean(name="datasourceDs2") public DataSource datasourceDs2(@Qualifier("db2Config") DbConfig config1) { MysqlXADataSource mysqlXADataSource=new MysqlXADataSource(); mysqlXADataSource.setUrl(config1.getUrl()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXADataSource.setPassword(config1.getPassword()); mysqlXADataSource.setUser(config1.getUsername()); AtomikosDataSourceBean atomikosDataSourceBean=new AtomikosDataSourceBean(); atomikosDataSourceBean.setXaDataSource(mysqlXADataSource); atomikosDataSourceBean.setUniqueResourceName("datasourceDs2"); // atomikosDataSourceBean.setMinPoolSize(config1.getMinPoolSize()); // atomikosDataSourceBean.setMaxPoolSize(config1.getMaxPoolSize()); // atomikosDataSourceBean.setMaxLifetime(config1.getMaxLifetime()); // atomikosDataSourceBean.setBorrowConnectionTimeout(config1.getBorrowConnectionTimeout()); // atomikosDataSourceBean.setLoginTimeout(config1.getLoginTimeout()); // atomikosDataSourceBean.setMaintenanceInterval(config1.getMaintenanceInterval()); // atomikosDataSourceBean.setMaxIdleTime(config1.getMaxIdleTime()); return atomikosDataSourceBean; } // @Bean(name="ds2JdbcTemplate") // public JdbcTemplate ds2JdbcTemplate(@Qualifier("datasourceDs2")DataSource dataSource) { // return new JdbcTemplate(dataSource); // } @Bean(name = "ds2SqlSessionFactory") public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("datasourceDs2")DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); //添加XML目录 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/xml/*Mapper.xml")); return sqlSessionFactoryBean.getObject(); } @Bean(name = "ds2SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("ds2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
7. 配置多数据源事物的处理
package com.spf.boot.atomikos; import com.atomikos.icatch.jta.UserTransactionImp; import com.atomikos.icatch.jta.UserTransactionManager; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.transaction.jta.JtaTransactionManager; import javax.transaction.SystemException; import java.util.Properties; /*** * 分布式事物管理 */ @Configuration public class AutoProxyRegist { @Bean(name="atomikosTransactionManager",initMethod="init",destroyMethod="close") public UserTransactionManager userTransactionManager(){ UserTransactionManager transactionManager = new UserTransactionManager(); transactionManager.setForceShutdown(false); return transactionManager; } @Bean(name="atomikosUserTransaction") public UserTransactionImp userTransactionImp() throws SystemException { UserTransactionImp transactionImp = new UserTransactionImp(); transactionImp.setTransactionTimeout(120); return transactionImp; } @Bean("springTransactionManager") public JtaTransactionManager transactionManager( @Qualifier("atomikosTransactionManager") UserTransactionManager transactionManager, @Qualifier("atomikosUserTransaction") UserTransactionImp userTransaction) { JtaTransactionManager jtaTM = new JtaTransactionManager(); jtaTM.setTransactionManager(transactionManager); jtaTM.setUserTransaction(userTransaction); jtaTM.setAllowCustomIsolationLevels(true); return jtaTM; } @Bean(name = "txAdvice") public TransactionInterceptor getAdvisor(@Qualifier("springTransactionManager") JtaTransactionManager txManager) throws Exception { TransactionInterceptor tsi = new TransactionInterceptor(); Properties properties = new Properties(); properties.setProperty("get*", "PROPAGATION_SUPPORTS"); properties.setProperty("select*", "PROPAGATION_SUPPORTS"); properties.setProperty("load*", "PROPAGATION_SUPPORTS"); properties.setProperty("query*", "PROPAGATION_SUPPORTS"); properties.setProperty("list*", "PROPAGATION_SUPPORTS"); properties.setProperty("add*", "PROPAGATION_REQUIRED"); properties.setProperty("insert*", "PROPAGATION_REQUIRED"); properties.setProperty("save*", "PROPAGATION_REQUIRED"); properties.setProperty("update*", "PROPAGATION_REQUIRED"); properties.setProperty("modify*", "PROPAGATION_REQUIRED"); properties.setProperty("do*", "PROPAGATION_REQUIRED"); properties.setProperty("del*", "PROPAGATION_REQUIRED"); properties.setProperty("remove*", "PROPAGATION_REQUIRED"); properties.setProperty("process*", "PROPAGATION_REQUIRED"); properties.setProperty("create*", "PROPAGATION_REQUIRED"); properties.setProperty("valid*", "PROPAGATION_REQUIRED"); properties.setProperty("do*", "PROPAGATION_REQUIRED"); properties.setProperty("write*", "PROPAGATION_REQUIRED"); properties.setProperty("cancel*", "PROPAGATION_REQUIRED"); properties.setProperty("*", "readOnly"); tsi.setTransactionAttributes(properties); tsi.setTransactionManager(txManager); return tsi; } @Bean public BeanNameAutoProxyCreator txProxy() { BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator(); creator.setInterceptorNames("txAdvice"); creator.setBeanNames("*ServiceImpl"); creator.setProxyTargetClass(true); return creator; } }
8 mapper层根据上面映射建立三个,不同的文件夹处理不同的数据库
9. servicec层
此处的每个方法都是支持事物的,在前面AutoProxyRegist类已经配置,以insert开头的方法支持事物的
至此完工!