springboot多数据源,分布式事务管理atomikos,自动扫描service配置事务

1.使用的Atomikos:一个为Java平台提供增值服务的并且开源类事务管理器。

2.数据源配置:

@Configuration
public class DatasourceConfig {
	
	@Bean(destroyMethod = "close", name = DataSources.MASTER_DB)
	@Primary
    @Autowired
	public DataSource dataSource(Environment env) throws Exception {
		AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
        Properties prop = build(env, "spring.datasource.");
        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        ds.setUniqueResourceName(DataSources.MASTER_DB);
        ds.setPoolSize(5);
        ds.setXaProperties(prop);
        return ds;
	}
	@Autowired
	@Bean(destroyMethod = "close", name = DataSources.CLUSTER_DB)
	public DataSource datasourceCluster(Environment env) {
		AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
        Properties prop = build(env, "spring.datasourceCluster.");
        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        ds.setUniqueResourceName(DataSources.CLUSTER_DB);
        ds.setPoolSize(5);
        ds.setXaProperties(prop);
        return ds;
	}
	
	@Bean("clusterJdbcTemplate")
	public JdbcTemplate busJdbcTemplate(@Qualifier("businessDataSource") DataSource ds) {
		return new JdbcTemplate(ds);
	}
	
	private Properties build(Environment env, String prefix) {
        Properties prop = new Properties();
        prop.put("url", env.getProperty(prefix + "url"));
        prop.put("username", env.getProperty(prefix + "username"));
        prop.put("password", env.getProperty(prefix + "password"));
        prop.put("driverClassName", env.getProperty(prefix + "driverClassName", ""));
        prop.put("initialSize", env.getProperty(prefix + "initialSize", Integer.class));
        prop.put("maxActive", env.getProperty(prefix + "maxActive", Integer.class));
        prop.put("minIdle", env.getProperty(prefix + "minIdle", Integer.class));
        prop.put("maxWait", env.getProperty(prefix + "maxWait", Integer.class));
        prop.put("poolPreparedStatements", env.getProperty(prefix + "poolPreparedStatements", Boolean.class));

        prop.put("maxPoolPreparedStatementPerConnectionSize",
                env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));

        prop.put("maxPoolPreparedStatementPerConnectionSize",
                env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));
        prop.put("validationQuery", env.getProperty(prefix + "validationQuery"));
        prop.put("validationQueryTimeout", env.getProperty(prefix + "validationQueryTimeout", Integer.class));
        prop.put("testOnBorrow", env.getProperty(prefix + "testOnBorrow", Boolean.class));
        prop.put("testOnReturn", env.getProperty(prefix + "testOnReturn", Boolean.class));
        prop.put("testWhileIdle", env.getProperty(prefix + "testWhileIdle", Boolean.class));
        prop.put("timeBetweenEvictionRunsMillis",
                env.getProperty(prefix + "timeBetweenEvictionRunsMillis", Integer.class));
        prop.put("minEvictableIdleTimeMillis", env.getProperty(prefix + "minEvictableIdleTimeMillis", Integer.class));
        prop.put("filters", env.getProperty(prefix + "filters"));
        return prop;
    }
}
public interface DataSources {
    String MASTER_DB = "masterDB";
    String CLUSTER_DB = "clusterDB";
}
@Configuration
public class DruidMonitorConfig {
	@Bean
	public ServletRegistrationBean druidServlet() {
		ServletRegistrationBean reg = new ServletRegistrationBean();
		reg.setServlet(new StatViewServlet());
		reg.addUrlMappings("/druid/*");
		reg.addInitParameter("loginUsername", "admin");
		reg.addInitParameter("loginPassword", "123456");
		return reg;
	}

	@Bean
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new WebStatFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.addInitParameter("exclusions",
				"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
		filterRegistrationBean.addInitParameter("profileEnable", "true");
		filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
		filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
		return filterRegistrationBean;
	}
}

配置扫描mybatis扫描mapper:

@Configuration
@MapperScan(basePackages = { "com.xxx.mapper.cluster" }, sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class MybatisCluster {

	@Autowired
	@Qualifier(DataSources.CLUSTER_DB)
	private DataSource clusterDB;

	@Bean(name = "clusterSqlSessionFactory")
	@ConfigurationProperties(prefix = "mybatisCluster")
	public SqlSessionFactory sqlSessionFactoryCluster() throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(clusterDB);
		return sqlSessionFactoryBean.getObject();
	}
	
	@Bean("clusterJdbcTemplate")
	public JdbcTemplate sysJdbcTemplate() {
		return new JdbcTemplate(clusterDB);
	}
	
	@Bean
	public SqlSessionTemplate sqlSessionTemplateCluster() throws Exception {
		SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactoryCluster());
		return template;
	}
}
@Configuration
@MapperScan(basePackages = { "com.xxx.mapper.master" }, sqlSessionFactoryRef = "SqlSessionFactory")
public class MybatisConfig {
	
	@Autowired
	@Qualifier(DataSources.MASTER_DB)
	private DataSource masterDB;

	@Bean
	@Primary
	@ConfigurationProperties(prefix = "mybatis")
	public SqlSessionFactory SqlSessionFactory() throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(masterDB);
		return sqlSessionFactoryBean.getObject();
	}
	
	@Bean("masterJdbcTemplate")
	public JdbcTemplate sysJdbcTemplate() {
		return new JdbcTemplate(masterDB);
	}
	
	@Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(SqlSessionFactory()); // 使用上面配置的Factory
        return template;
    }
}

事务管理:

@Configuration
@ComponentScan
@EnableTransactionManagement
public class TransactionManagerConfig {
	
	@Bean(name = "userTransaction")
	public UserTransaction userTransaction() throws Throwable {
		UserTransactionImp userTransactionImp = new UserTransactionImp();
		userTransactionImp.setTransactionTimeout(10000);
		return userTransactionImp;
	}

	@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
	public UserTransactionManager atomikosTransactionManager() throws Throwable {
		UserTransactionManager userTransactionManager = new UserTransactionManager();
		userTransactionManager.setForceShutdown(false);
		return userTransactionManager;
	}

	@Bean(name = "transactionManager")
	@DependsOn({ "userTransaction", "atomikosTransactionManager" })
	public JtaTransactionManager transactionManager() throws Throwable {
		UserTransaction userTransaction = userTransaction();
		JtaTransactionManager manager = new JtaTransactionManager(userTransaction, atomikosTransactionManager());
		return manager;
	}

	@Bean(name = "transactionInterceptor")
	public TransactionInterceptor transactionInterceptor(PlatformTransactionManager platformTransactionManager) {
		TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
		// 事物管理器
		transactionInterceptor.setTransactionManager(platformTransactionManager);
		Properties transactionAttributes = new Properties();
		
		// 新增
		transactionAttributes.setProperty("insert*", "PROPAGATION_REQUIRED,-Throwable");
		transactionAttributes.setProperty("save*", "PROPAGATION_REQUIRED,-Throwable");
		// 修改
		transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED,-Throwable");
		// 删除
		transactionAttributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Throwable");
		// 查询
		transactionAttributes.setProperty("select*", "PROPAGATION_REQUIRED,-Throwable,readOnly");

		transactionInterceptor.setTransactionAttributes(transactionAttributes);
		return transactionInterceptor;

	}

	// 代理到ServiceImpl的Bean
	@Bean
	public BeanNameAutoProxyCreator transactionAutoProxy() {
		BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();
		transactionAutoProxy.setProxyTargetClass(true);
		transactionAutoProxy.setBeanNames("*ServiceImpl");
		transactionAutoProxy.setInterceptorNames("transactionInterceptor");
		return transactionAutoProxy;
	}
}

3.application.yml

spring:
  mail:
    host: 
    username: 
    password: 
    properties: 
      mail: 
        smtp: 
          auth: true
  datasource:
#   数据源基本配置
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/xxxx?characterEncoding=UTF-8&useSSL=false
    type: com.alibaba.druid.pool.DruidDataSource
#   数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    validationQueryTimeout: 10000
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
#   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    # 合并多个DruidDataSource的监控数据
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  datasourceCluster:
#   数据源基本配置
    username: admin
    password: [email protected]
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/xxx?characterEncoding=UTF-8&useSSL=false
    type: com.alibaba.druid.pool.DruidDataSource
#   数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    validationQueryTimeout: 10000
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
#   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
#   合并多个DruidDataSource的监控数据
    useGlobalDataSourceStat: true
#jta相关参数配置   
jta:
  log-dir: classpath:tx-logs
  transaction-manager-id: txManager
mybatis:
  # 指定全局配置文件位置
  config-location: classpath:mybatis/mybatis-config.xml
  # 指定sql映射文件位置
  mapper-locations: classpath:com/xxx/mapper/master/*.xml
mybatisCluster:
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:com/xxx/mapper/cluster/*.xml

4.maven配置:

 <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-jta-atomikos</artifactId>
	    </dependency>
	    <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

5.测试:

@Override
	public ServerResponseDTO<String> saveTest() {
		User user = new User();
		user.setUsername("test");
		user.setUpdateTime(new Date());
		user.setCreateTime(user.getUpdateTime());
		user.setPassword("123456");
		userMapper.insertSelective(user);
		TbUser tbUser = new TbUser();
		tbUser.setUsername("test");
		tbUser.setPassword("123456");
		tbUser.setUpdated(new Date());
		tbUser.setCreated(new Date());
		int a = tbUserMapper.insertSelective(tbUser);
		if(a < 1)
			throw new RuntimeException("1");
		return ServerResponseDTO.createBySuccess();
	}



猜你喜欢

转载自blog.csdn.net/u014172271/article/details/80304403
今日推荐