在开发业务中可能因为数据量巨大,或者并发量大,又或者因为其他的种种原因,一个数据无法满足我们的需求,那么如何在同一个项目中配置多个数据库呢?下面就简单说一下简单的多数据源配置(这里都以mysql为例)
一、添加yml配置
相信单一数据源的配置大家都很熟悉,而多数据源的配置也非常简单,直接上码:
#读写分离的多数据源
#读库
datasource:
read:
jdbc-url: jdbc:mysql:///mark_read?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
#写库
write:
jdbc-url: jdbc:mysql:///market?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
可以看到为了方便区分,我再两个数据源的配置上分别以read和write来区分,当然,这不是绝对的,你也可以用test1,test2等等都可以,在接下来要说的配置类中需要通过指定这个配置来读取相关信息
二、增加配置类
为两个数据源分别增加配置,配置的时候用@Primary
指定哪个是主库,一般如果是读写分离的话写为主库
1、数据源1
package com.wwy.config;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
/**
* 多数据源的数据源配置类(读)
* @author wwy
* @date 2019年12月12日
* @version v0.0.1
*
* 配置数据源通常需要配置以下bean:
* DataSource
* SqlSessionFactory
* SqlSessionTemplate
*/
@MapperScan(basePackages = "com.wwy.**.read",
sqlSessionFactoryRef = "readSqlSessionFactory")
@Configuration
public class ReadDataSourceConfig {
/**
* 1.DataSource
*/
//务必为bean添加名字,因为多数据源注入时需要按照名字注入,否则会引起冲突
@Bean("readDataSource")
//指定yml中配置的参数的前缀
@ConfigurationProperties("spring.datasource.read")
public DataSource readDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 2.SqlSessionFactory
* @throws Exception
*/
@Bean("readSqlSessionFactory")
public SqlSessionFactory readSqlSessionFactory(
//这里注意:要按名称注入!
@Qualifier("readDataSource")DataSource dataSource) throws Exception {
SqlSessionFactoryBean ssf=new SqlSessionFactoryBean();
//指定数据源
ssf.setDataSource(dataSource);
//指定xml位置
ssf.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/read/*.xml")
);
return ssf.getObject();
}
/**
* 3.SqlSessionTemplate
*/
@Bean("readSqlSessionTemplate")
public SqlSessionTemplate readSqlSessionTemplate(@Qualifier("readSqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
2、数据源2
package com.wwy.config;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
/**
* 多数据源的数据源配置类(写)
* @author wwy
* @date 2019年12月12日
* @version v0.0.1
*
* 配置数据源通常需要配置以下bean:
* DataSource
* SqlSessionFactory
* SqlSessionTemplate
*/
@Primary
@Configuration
@MapperScan(basePackages = "com.wwy.**.write",
sqlSessionFactoryRef = "writeSqlSessionFactory")
public class WriteDataSourceConfig {
/**
* 1.DataSource
*/
//务必为bean添加名字,因为多数据源注入时需要按照名字注入,否则会引起冲突
@Bean("writeDataSource")
//指定yml中配置的参数的前缀
@ConfigurationProperties("spring.datasource.write")
public DataSource writeDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 2.SqlSessionFactory
* @throws Exception
*/
@Bean("writeSqlSessionFactory")
public SqlSessionFactory writeSqlSessionFactory(
//这里注意:要按名称注入!
@Qualifier("writeDataSource")DataSource dataSource) throws Exception {
SqlSessionFactoryBean ssf=new SqlSessionFactoryBean();
//指定数据源
ssf.setDataSource(dataSource);
//指定xml位置
ssf.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/write/*.xml")
);
return ssf.getObject();
}
/**
* 3.SqlSessionTemplate
*/
@Bean("writeSqlSessionTemplate")
public SqlSessionTemplate writeSqlSessionTemplate(@Qualifier("writeSqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
三、使用
切记按照配置类中指定的mapper路径规则和xml路径规则,接下来就使我们常规的码代码了,这里就不再赘述!写完可以测试一下。
注意:1.如果出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
的异常,首先检查配置类中是否忘写@MapperScan(basePackages = "com.wwy.**.write", sqlSessionFactoryRef = "writeSqlSessionFactory")
的注解,这个注解是必须写的,不要认为不写这个注解,直接在接口上添加@mapper注解就可以了,我试验是不可以的;其次是xml文件位置是否指定,然后是检查namespace的值是否正确;如果都没有问题,数据源是可以正常使用的!
2.在配置类中的bean必须指定名字,注入时也必须按照名字注入,防止冲突。