下面我将详细讲解“多数据源@DS和@Transactional实战”的完整攻略。
一、多数据源@DS实战
1.1 添加多数据源配置
首先,在Spring Boot项目中添加多数据源配置。在application.yml文件中添加:
spring:
datasource:
test1:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
username: root
password: 123456
test2:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
username: root
password: 123456
上面的配置中,test1和test2就是我们要使用的两个数据源,分别对应了两个不同的数据库。其中,每个数据源都需要配置具体的数据库连接参数,包括驱动类名、数据库链接地址、用户名和密码等。
1.2 配置Mybatis-Plus
接下来,我们需要配置Mybatis-Plus,以支持多数据源。在配置类中添加以下代码:
@Configuration
@MapperScan("com.example.demo.mapper")
public class MybatisPlusConfig {
@Bean
@ConfigurationProperties("spring.datasource.test1")
public DataSource test1DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.test2")
public DataSource test2DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put("test1", test1DataSource());
dataSourceMap.put("test2", test2DataSource());
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(test1DataSource());
return dynamicDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:/mapper/*.xml"));
return bean.getObject();
}
}
上述代码中,我们先定义了两个数据源,同时也实例化了一个DynamicDataSource对象,并将这两个数据源添加到其中,最后将DynamicDataSource设置为我们的SqlSessionFactory的数据源。这里需要注意一下,我们需要自己编写一个DynamicDataSource类来实现动态数据源切换,这里不再赘述。
1.3 定义Mapper和Service
在使用多数据源之前,我们需要分别为每个数据源定义对应的Mapper接口,在Mapper接口上添加@DS注解,指定使用哪个数据源。Mapper接口示例代码如下:
@DS("test1")
public interface Test1Mapper {
@Select("SELECT * FROM test1")
List<Test1> selectAll();
}
@DS("test2")
public interface Test2Mapper {
@Select("SELECT * FROM test2")
List<Test2> selectAll();
}
接着,在Service层中注入对应的Mapper。
@Service
public class TestServiceImpl implements TestService {
@Autowired
private Test1Mapper test1Mapper;
@Autowired
private Test2Mapper test2Mapper;
@Override
public List<Test1> getTest1Data() {
return test1Mapper.selectAll();
}
@Override
public List<Test2> getTest2Data() {
return test2Mapper.selectAll();
}
}
当我们调用getTest1Data()方法时,Mybatis Plus会自动使用test1Mapper对应的数据源执行相应的查询操作。类似地,当我们调用getTest2Data()方法时,Mybatis Plus会使用test2Mapper对应的数据源执行查询操作。
二、@Transactional实战
上述示例只是简单地演示了多数据源的使用方法,如果要在具体的业务场景中使用,还需要引入事务管理机制。这里我们将使用@Transactional注解来管理事务。
2.1 配置事务管理器
要使用@Transactional注解,我们需要打开@Transactional注解的事务支持,并配置事务管理器。注意,我们需要给每个数据源配置单独的事务管理器。修改配置类,代码如下:
@Configuration
@EnableTransactionManagement
@MapperScan("com.example.demo.mapper")
public class MybatisPlusConfig {
// ...
@Bean
@Primary
public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
@Bean
public PlatformTransactionManager test1TransactionManager() {
return new DataSourceTransactionManager(test1DataSource());
}
@Bean
public PlatformTransactionManager test2TransactionManager() {
return new DataSourceTransactionManager(test2DataSource());
}
}
2.2 定义Service方法
接下来,我们需要在Service层中定义一个包含事务操作的方法,在该方法上添加@Transactional注解,以管理事务。下面给出示例代码:
@Service
public class TestServiceImpl implements TestService {
@Autowired
private Test1Mapper test1Mapper;
@Autowired
private Test2Mapper test2Mapper;
@Override
@Transactional(transactionManager = "test1TransactionManager", rollbackFor = Exception.class)
public void insertTest1AndTest2() throws Exception {
Test1 test1 = new Test1();
test1.setName("test1");
test1Mapper.insert(test1);
Test2 test2 = new Test2();
test2.setName("test2");
test2Mapper.insert(test2);
if (new Random().nextBoolean()) {
throw new Exception("test1万岁");
}
}
}
在上述代码中,我们定义一个insertTest1AndTest2()方法,当我们插入test1和test2数据时,如果出现异常,则事务会回滚。
2.3 测试
最后,我们可以在Controller中编写测试代码,以测试事务管理效果。测试代码如下:
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/multi-datasource/transactional-test")
public String transactionalTest() {
try {
testService.insertTest1AndTest2();
return "success";
} catch (Exception e) {
return "failed";
}
}
}
在该Controller中,我们定义了一个transactionalTest()方法,该方法调用了Service层的insertTest1AndTest2()方法,对test1和test2两个数据源进行了插入操作。当插入操作发生异常时,该方法返回"failed",否则返回"success"。
总结
至此,我们完成了“多数据源@DS和@Transactional实战”的完整攻略,包括了多数据源的配置、Mapper和Service定义、事务管理器和@Transactional注解的使用等。在实际项目中,我们可以根据需要将这些技术结合起来,实现动态数据源切换和事务管理等功能,提高系统的稳定性和可靠性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:多数据源@DS和@Transactional实战 - Python技术站