1、绑定第一个数据库
/**
* 创建多数据源的过程就是:首先创建 DataSource,
* 注入到 SqlSessionFactory 中,再创建事务,
* 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中,
* 最后将 SqlSessionTemplate 注入到对应的 Mapper 包路径下。
* 其中需要指定分库的 Mapper 包路径。
*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.test.datasource1",sqlSessionTemplateRef = "sqlSessionTemplate1")
public class DataSourceConfig1 {
/**
* 创建 DataSource
* @return
*/
@Bean(name="dataSource1")
//配置文件中数据库的参数
@ConfigurationProperties(prefix = "spring.datasource.hikari.data1")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
/**
* 注入到 SqlSessionFactory 中
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionFactory1")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource) throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/dao/mapper/dao1/*.xml"));
return bean.getObject();
}
//配置事务
@Bean(name = "transactionManagerTest1")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource1") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
/**
* 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中
* @param sqlSessionFactory
* @return
*/
@Bean(name="sqlSessionTemplate1")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
//配置事务
//注意这个bean名transactionManager1,将在TxAdviceInterceptor文件中使用
@Bean
public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
2、绑定第二个数据库
/**
* 创建多数据源的过程就是:首先创建 DataSource,
* 注入到 SqlSessionFactory 中,再创建事务,
* 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中,
* 最后将 SqlSessionTemplate 注入到对应的 Mapper 包路径下。
* 其中需要指定分库的 Mapper 包路径。
*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.test.datasource2",sqlSessionTemplateRef = "sqlSessionTemplate2")
public class DataSourceConfig2 {
/**
* 创建 DataSource
* @return
*/
@Bean(name="dataSource2")
//配置文件中数据库的参数
@ConfigurationProperties(prefix = "spring.datasource.hikari.data2")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
/**
* 注入到 SqlSessionFactory 中
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionFactory2")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource2") DataSource dataSource) throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/test/dao/mapper/dao2/*.xml"));
return bean.getObject();
}
//配置事务
@Bean(name = "transactionManagerTest2")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource2") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
/**
* 将 SqlSessionFactory 注入到创建的 SqlSessionTemplate 中
* @param sqlSessionFactory
* @return
*/
@Bean(name="sqlSessionTemplate2")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
//配置事务
//注意这个bean名transactionManager2
@Bean
public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
3、application-dev.yml配置文件
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
hikari:
mdm:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 620000
maximum-pool-size: 30
minimum-idle: 5
pool-name: DatebookHikariCP
msg:
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 620000
maximum-pool-size: 30
minimum-idle: 5
pool-name: DatebookHikariCP
4、配置全局事务
@Aspect
@Configuration
public class TxAdviceInterceptor {
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.test.service.impl.*.*(..))";
@Autowired
private PlatformTransactionManager transactionManager1;//刚才设置的bean
@Bean
public TransactionInterceptor txAdvice() {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/* 当前没有事务:只有select,非事务执行;有update,insert,delete操作,自动提交;
* 当前有事务:如果有update,insert,delete操作,支持当前事务 */
/*只读事务,不做更新操作*/
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
/* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务 */
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// requiredTx.setTimeout(TX_METHOD_TIMEOUT);
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("get*", readOnlyTx);
txMap.put("*", requiredTx);
source.setNameMap(txMap);
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager1, source);
return txAdvice;
}
@Bean
public Advisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, txAdvice());
}
}
5、springboot启动文件
//war部署到tomcat
@EnableAsync
@EnableTransactionManagement//开启事务
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableScheduling
@MapperScan({"com.test.dao.persistence"})
public class AdminApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(AdminApplication.class);
}
//返回设置为utf-8
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
}
注意:
只能在一个数据源上配置全局事务。不使用TxAdviceInterceptor文件的话,还可以在service文件上或者service方法上使用注解
@Transactional(transactionManager = "transactionManager1"),注解上必须标明是使用哪个事务
这样就会对相关service文件中报错了,设计到第一个数据源的就会回滚