java mybaits 读写分离_Mybatis多数据源读写分离(注解实现)

本文介绍了如何使用SpringBoot、MyBatis和Druid实现Java应用的读写分离,通过注解的方式动态切换数据源。详细步骤包括配置主从数据库、创建动态数据源、定义切换注解、AOP切面处理以及测试Controller。
摘要由CSDN通过智能技术生成

Mybatis多数据源读写分离(注解实现)

首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒,喜喜),表结构

表名 t_user

| 字段名 | 类型 | 备注 |

| :------: | :------: | :------: |

| id | int | 主键自增ID |

| name | varchar | 名称 |

77dba6aa182ebeaf178512a58a5edcad.png

表中分别添加两条不同数据,方便测试

主数据库记录name为xiaobin,从库为xiaoliu

开始使用Springboot 整合mybatis,首先引入pom文件

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.4.RELEASE

com.xiaobin

mysql_master_slave

1.0-SNAPSHOT

1.8

1.18.6

1.3.2

1.18.6

org.springframework.boot

spring-boot-starter-web

org.projectlombok

lombok

${lombok.version}

org.springframework.boot

spring-boot-starter-test

org.projectlombok

lombok

${lombox.version}

org.mybatis.spring.boot

mybatis-spring-boot-starter

${mybatis.version}

mysql

mysql-connector-java

org.springframework.boot

spring-boot-starter-jdbc

com.alibaba

druid-spring-boot-starter

1.1.10

org.springframework.boot

spring-boot-starter-aop

动态数据源配置

这里使用的数据源为druid,实现数据源之间的切换用@DataSource自定义注解,配置Aop进行切换

application.yml 配置文件

spring:

datasource:

type: com.alibaba.druid.pool.DruidDataSource

druid:

xiaobin-master: # 主数据源

driverClassName: com.mysql.jdbc.Driver

username: root

password: root

url: jdbc:mysql://localhost:3306/master_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8

xiaobin-slave: # 从数据源

driverClassName: com.mysql.jdbc.Driver

username: root

password: root

url: jdbc:mysql://localhost:3306/slave_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8

mybatis:

mapper-locations: classpath:mapper/*.xml

多数据源配置类

package com.xiaobin.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;

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.stereotype.Component;

import javax.sql.DataSource;

import java.util.HashMap;

import java.util.Map;

/**

* 创建时间: 2019/9/22 11:42

* 备注:多数据源配置信息

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

@Configuration

@Component

public class DynamicDataSourceConfig {

@Bean

@ConfigurationProperties("spring.datasource.druid.xiaobin-master")

public DataSource xiaobinMasterDataSource(){

return DruidDataSourceBuilder.create().build();

}

@Bean

@ConfigurationProperties("spring.datasource.druid.xiaobin-slave")

public DataSource xiaobinSlaveDataSource(){

return DruidDataSourceBuilder.create().build();

}

@Bean

@Primary

public DynamicDataSource dataSource(DataSource xiaobinMasterDataSource, DataSource xiaobinSlaveDataSource) {

Map targetDataSources = new HashMap<>();

targetDataSources.put("xiaobin-master",xiaobinMasterDataSource);

targetDataSources.put("xiaobin-slave", xiaobinSlaveDataSource);

return new DynamicDataSource(xiaobinMasterDataSource, targetDataSources);

}

}

动态数据源切换类

package com.xiaobin.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import org.springframework.lang.Nullable;

import javax.sql.DataSource;

import java.util.Map;

/**

* 创建时间: 2019/9/22 11:51

* 备注:动态数据源

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

public class DynamicDataSource extends AbstractRoutingDataSource {

private static final ThreadLocal contextHolder = new ThreadLocal<>();

public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {

super.setDefaultTargetDataSource(defaultTargetDataSource);

super.setTargetDataSources(targetDataSources);

super.afterPropertiesSet();

}

@Override

protected Object determineCurrentLookupKey() {

return getDataSource();

}

public static void setDataSource(String dataSource) {

contextHolder.set(dataSource);

}

public static String getDataSource() {

return contextHolder.get();

}

public static void clearDataSource() {

contextHolder.remove();

}

}

自定义@DataSource注解

在需要切换数据的Dao添加此注解

package com.xiaobin.annotation;

import java.lang.annotation.*;

/**

* 创建时间: 2019/9/22 11:53

* 备注:自定义数据源选择注解

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface DataSource {

String name() default "";

}

Aop切面类配置

package com.xiaobin.aspect;

import com.xiaobin.annotation.DataSource;

import com.xiaobin.config.DynamicDataSource;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;

import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**

* 创建时间: 2019/9/22 11:54

* 备注:

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

@Aspect

@Component

public class DataSourceAspect {

@Pointcut("@annotation(com.xiaobin.annotation.DataSource)")

public void dataSourcePointCut() {

}

@Around("dataSourcePointCut()")

public Object around(ProceedingJoinPoint point) throws Throwable {

MethodSignature signature = (MethodSignature) point.getSignature();

Method method = signature.getMethod();

DataSource dataSource = method.getAnnotation(DataSource.class);

if(dataSource == null){

DynamicDataSource.setDataSource("xiaobin-master");

}else {

DynamicDataSource.setDataSource(dataSource.name());

}

try {

return point.proceed();

} finally {

DynamicDataSource.clearDataSource();

}

}

}

启动配置注解信息,重要(不然运行会报错)

package com.xiaobin;

import com.xiaobin.config.DynamicDataSourceConfig;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

import org.springframework.context.annotation.Import;

/**

* 创建时间: 2019/9/22 11:17

* 备注:

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})

@MapperScan(basePackages = "com.xiaobin.mapper")

@Import({DynamicDataSourceConfig.class})

public class StartApp {

public static void main(String[] args) {

SpringApplication.run(StartApp.class);

}

}

测试controller

package com.xiaobin.api;

import com.xiaobin.Entity.TUser;

import com.xiaobin.mapper.UserMapper;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**

* 创建时间: 2019/9/22 12:08

* 备注:

* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

**/

@RestController

@RequestMapping

public class UserController {

@Autowired

private UserMapper userMapper;

@GetMapping("/{name}/list")

public List list(@PathVariable("name")String name){

if(name.equals("master")){

return userMapper.queryAllWithMaster();

}else{

return userMapper.queryAllWithSlave();

}

}

}

效果图

更具路径传值,进行主从数据源切换

570d398ad690e35b68200a28e141a716.png

e3642e7dcacfbb5c529379b7e28f2d18.png

目录结构

aa257fa3164c9d425edf3542c62ed788.png

码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值