springboot+mybatisplus+druid实现主从分离
时间: 2023-09-11 09:06:23 浏览: 335
主从分离是一种常见的数据库优化策略,在高并发场景下可以提升系统的性能和可用性。下面是使用 Spring Boot、Mybatis Plus 和 Druid 实现主从分离的步骤:
1. 引入依赖
在 pom.xml 文件中引入以下依赖:
```xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
```
2. 配置数据源
在 application.yml 文件中配置主从数据源的信息:
```yaml
spring:
datasource:
master:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/master_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: root
slave:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3307/slave_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: root
```
其中,master 和 slave 分别代表主库和从库的配置信息。
3. 配置 Druid 数据源
在 application.yml 文件中添加 Druid 数据源的配置:
```yaml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall,log4j
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
```
4. 配置 Mybatis Plus
在 application.yml 文件中添加 Mybatis Plus 的配置:
```yaml
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
global-config:
db-config:
id-type: auto
field-strategy: not_null
table-prefix: mp_
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
```
其中,mapper-locations 配置了 Mybatis Plus 的 Mapper 文件路径,global-config 配置了一些全局的配置,configuration 配置了 Mybatis 的一些参数。
5. 实现动态数据源
创建 DynamicDataSource 类,继承 AbstractRoutingDataSource,并实现 determineCurrentLookupKey() 方法:
```java
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.get();
}
}
```
其中,DataSourceContextHolder 是一个线程安全的类,用于存储当前线程使用的数据源类型。
6. 配置数据源路由
创建 DataSourceConfiguration 类,配置数据源路由:
```java
@Configuration
public class DataSourceConfiguration {
@Bean
public DataSource masterDataSource() {
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public DataSource slaveDataSource() {
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public DynamicDataSource dynamicDataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put("master", masterDataSource());
dataSourceMap.put("slave", slaveDataSource());
dataSource.setTargetDataSources(dataSourceMap);
dataSource.setDefaultTargetDataSource(masterDataSource());
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
return sqlSessionFactoryBean.getObject();
}
}
```
其中,masterDataSource() 和 slaveDataSource() 分别返回主库和从库的 Druid 数据源,dynamicDataSource() 返回动态数据源,sqlSessionFactory() 配置了 Mybatis 的 SqlSessionFactory。
7. 实现数据源切换
创建 DataSourceContextHolder 类,用于在当前线程上存储数据源的类型:
```java
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void set(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String get() {
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
}
```
创建 DataSourceAspect 类,实现切面拦截:
```java
@Aspect
@Component
public class DataSourceAspect {
@Before("@annotation(com.example.demo.annotation.Master) ")
public void setMasterDataSource() {
DataSourceContextHolder.set("master");
}
@Before("@annotation(com.example.demo.annotation.Slave) ")
public void setSlaveDataSource() {
DataSourceContextHolder.set("slave");
}
@After("@annotation(com.example.demo.annotation.Master) || @annotation(com.example.demo.annotation.Slave)")
public void clearDataSource() {
DataSourceContextHolder.clear();
}
}
```
其中,@Master 和 @Slave 是自定义的注解,用于标记使用主库和从库。
8. 实现主从分离
在 Mybatis Plus 的 Mapper 接口中,使用 @Master 和 @Slave 注解标记方法,实现主从分离:
```java
public interface UserMapper extends BaseMapper<User> {
@Master
User selectById(Integer id);
@Slave
List<User> selectAll();
}
```
其中,selectById() 方法使用主库,selectAll() 方法使用从库。
9. 测试主从分离
使用 JUnit 进行测试:
```java
@SpringBootTest
class DemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
User user = userMapper.selectById(1);
System.out.println(user.getName());
}
@Test
void testSelectAll() {
List<User> userList = userMapper.selectAll();
userList.forEach(user -> System.out.println(user.getName()));
}
}
```
其中,contextLoads() 方法测试使用主库,testSelectAll() 方法测试使用从库。
以上就是使用 Spring Boot、Mybatis Plus 和 Druid 实现主从分离的步骤。
阅读全文