spring配置主库从库_springboot集成mybatis配置主从复制双
库实现读写分离
⼀般情况下⽹站对数据库的读要⽐写多多了,所以当数据量⼤了的时候,使⽤读写分离是很有必要的
spring提供了数据源路由的类,正好拿它来实现⼀下
创建项⽬
简单的springboot项⽬,依赖有mybatis,mysql,aspect
springboot版本是 2.2.0.RELEASE
org.springframework.boot
spring-boot-starter
mybatis-spring-boot-starter
2.1.1
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-aop
数据
我测试的两个库,⼀个主库⼀个从库,只有⼀个表,数据如下
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- 主库的数据
INSERT INTO `user` (`id`, `username`)
VALUES
(1, 'tomoya'),
(2, '朋也');
-- 从库的数据
INSERT INTO `user` (`id`, `username`)
VALUES
(1, 'tomoya');
可以看到从库中少了⼀条数据,这样可以对⽐看读写分离的功能是否⽣效了
配置
⾸先就是springboot的双数据源的配置
spring:
datasource:
master:
jdbc-url: jdbc:mysql://192.168.16.87:3306/pybbs?
useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root
password: 123123
driver-class-name: sql.cj.jdbc.Driver
slave:
jdbc-url: jdbc:mysql://192.168.16.109:3306/pybbs?
useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root
password: 123123
driver-class-name: sql.cj.jdbc.Driver
使⽤java代码来创建两个数据源, 创建类 MyDataSource.java
@Configuration
public class MyDataSource {
/
/ 主库数据源
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
ate().build();
}
// 从库数据源
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
ate().build();
}
// 数据源路由
@Bean
public DataSource dynamicDatasource() {
Map dataSourceMap = new HashMap<>();
dataSourceMap.put(MultipleDataSourceHelper.MASTER, masterDataSource());
dataSourceMap.put(MultipleDataSourceHelper.SLAVE, slaveDataSource());
DynamicDataSource dds = new DynamicDataSource();
dds.setTargetDataSources(dataSourceMap);
dds.setDefaultTargetDataSource(masterDataSource());
return dds;
}
}
其中数据源路由是⼀个⾃定义的类,继承了spring提供的类AbstractRoutingDataSource,然后实现⾥⾯的⼀个⽅法determineCurrentLookupKey() 即可,这个⽅法返回的值就是⽤哪个数据源
查看类AbstractRoutingDataSource可以看到,⾥⾯有两个变量
private Map targetDataSources;
private Object defaultTargetDataSource;
targetDataSources是⼀个数据库的map集合,key是⾃定义的,可以随便指定,value就是配置好的数据源,如下代码
defaultTargetDataSource是默认的数据源,如果指定的key在targetDataSources⾥没有到对应的value,那么就会使⽤这个默认的数据源,防⽌程序出错
Map dataSourceMap = new HashMap<>();
dataSourceMap.put(MultipleDataSourceHelper.MASTER, masterDataSource());
dataSourceMap.put(MultipleDataSourceHelper.SLAVE, slaveDataSource());
DynamicDataSource dds = new DynamicDataSource();
dds.setTargetDataSources(dataSourceMap);
dds.setDefaultTargetDataSource(masterDataSource());
既然是⼀个map,value是数据源,那key最好建⼀个类管理起来⽐较好
public class MultipleDataSourceHelper {
public static final String MASTER = "master";
public static final String SLAVE = "slave";
private static ThreadLocal contextHolder = new ThreadLocal<>();
public static void set(String db) {
contextHolder.set(db);
}
public static String get() {
();
}
}
实现数据源路由
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
();
}
}
可以看到这⾥动态指定的数据源是从⾃定义管理key的类中取的,所以要想让CRUD的操作⾛主库还是从库就只需要改变MultipleDataSourceHelper ⾥的 contextHolder 就⾏了
mybatis配置
如果是单数据源,利⽤spring的配置⽂件就可以了,也就不⽤单独对mybatis进⾏配置了,这⾥数据源我是⾃⼰配置的,所以还要单独配置⼀下mybatis,给它指定⼀个数据源,如下
@Configuration
public class MyBatisConfig {
@Autowired
private DataSource dynamicDatasource;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 给mybatis指定上⾯配置好的动态数据源
sqlSessionFactoryBean.setDataSource(dynamicDatasource);
// ⾃⼰配置mybatis的话,这个必须要指定mapper位置,在l⾥配置的不会⽣效了
sqlSessionFactoryBean.setMapperLocations(new
PathMatchingResourcePatternResolver().getResources("classpath:mapper/*l"));
Object();
}
}
如果⽤l配置的话,只需要在 Mapper 上加⼀个注解即可 @Mapper 但⾃⼰配置的mybati
s就要扫包了,在启动类上添加注解 @MapperScan("ample.multipledatasource.mapper")
有了这个注解,Mapper上的 @Mapper 就不⽤要了
实体类,mapper
这⾥我⽤的实体类mapper跟上⼀篇博客是⼀样的,下⾯再贴⼀下吧User.java
public class User {
private Integer id;
private String username;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
'}';
}
}
UserMapper.java
//@Mapper
springboot aop
public interface UserMapper {
// 注解⽅式查询
@Select("select * from user;")
List selectAll();
/
/ xml⽅式查询
List selectAllWithXml();
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。