该主题概念
谈到数据源不陌生,中小型项目中偶尔也会遇到需要配置多数据源的问题。配置多数据源的核心在于如何配置,怎么让他加载,自己又是怎么区分。在开始之前,简单的介绍下实现的思路,spring boot的数据源默认加载方式肯定是不可行的,所以我们需要将默认加载数据源给注销掉,而自己配置数据源的重点在于你需要知道数据源配置在哪里。
多数据源demo
这里创建一个简单的spring boot项目即可。源码地址在最下方
注销默认配置
项目创建好了之后,在application启动类里,注销掉默认的数据源加载。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 去除数据库自动加载
public class AccessingMultiDataSourceApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingMultiDataSourceApplication.class, args);
}
}
多数据源配置
application.properties:这里不需多说,数据源的一些基本参数。
spring.datasource.primary.jdbc-url=jdbc:mysql://47.96.30.54:3306/primary
spring.datasource.primary.username=root
spring.datasource.primary.password=
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.second.jdbc-url=jdbc:mysql://47.96.30.54:3306/second
spring.datasource.second.username=root
spring.datasource.second.password=
spring.datasource.second.driver-class-name=com.mysql.cj.jdbc.Driver
DataSourceConfig:这里创建所需的多数据源
package com.example.demo.config;
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 javax.sql.DataSource;
/**
* Created by 神烦 on 2019/9/4.
* 因为去掉了数据源自动加载 所有要手动加载数据源
*/
@Configuration
public class DataSourceConfig {
// 主库
@Bean(name = "primarySource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource PrimarySource() {
return DataSourceBuilder.create().build();
}
// 从库
@Bean(name = "secondSource")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource SecondSource() {
return DataSourceBuilder.create().build();
}
}
primaryDataSource,SecondDataSource:这里配置多数据源mybatis的所需参数
package com.example.demo.config;
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.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* Created by 神烦 on 2019/9/6.
*/
@Configuration
@MapperScan(basePackages = {"com.example.demo.primary"}, sqlSessionFactoryRef = "PrimarySqlSessionFactory") // mapper包basePackages扫描路径 指定sqlSessionFactory
public class PrimaryDBConfig {
@Autowired
@Qualifier("primarySource") // 指定名称注入 该注释就是为了区分多个相同Bean不同名称的注入方法
private DataSource dataSource;
@Bean // 注入数据源
@Qualifier("primarySqlSession")
public SqlSessionFactory PrimarySqlSessionFactory() throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate SqlSessionTemplate1() throws Exception{
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(PrimarySqlSessionFactory());
return sqlSessionTemplate;
}
}
package com.example.demo.config;
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.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* Created by 神烦 on 2019/9/6.
* 从库的配置和主库差不多 注意的是数据源不要注入错误 和扫描的路径
*/
@Configuration
@MapperScan(basePackages = {"com.example.demo.second"}, sqlSessionFactoryRef = "SecondSqlSessionFactory") // mapper包basePackages扫描路径 指定sqlSessionFactory
public class SecondDBConfig {
@Autowired
@Qualifier("secondSource") // 指定名称注入 该注释就是为了区分多个相同Bean不同名称的注入方法
private DataSource dataSource;
@Bean // 注入数据源
@Qualifier("secondSqlSession")
public SqlSessionFactory SecondSqlSessionFactory() throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate SqlSessionTemplate2() throws Exception{
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(SecondSqlSessionFactory());
return sqlSessionTemplate;
}
}
多数据源数据准备
因为demo所以一切从简,我是创建了多个库,相同的表,不同的数据方便测试。
DROP TABLE IF EXISTS `t_test`;
CREATE TABLE `t_test` (
`ID` bigint(20) NOT NULL COMMENT '主键',
`NAME` varchar(255) DEFAULT NULL COMMENT '名称',
`REMARK` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
实体类
package com.example.demo.model;
import lombok.Data;
/**
* Created by 神烦 on 2019/9/6.
*/
@Data
public class Test {
private Long id;
private String name;
private String remark;
}
dao
根据不同数据源的basePackage到指定路径创建dao
package com.example.demo.primary;
import com.example.demo.model.Test;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
/**
* Created by 神烦 on 2019/9/6.
*/
@Mapper
public interface IPrimaryDao {
@Select("select * from t_test")
Test PrimaryTest();
}
second:
package com.example.demo.second;
import com.example.demo.model.Test;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
/**
* Created by 神烦 on 2019/9/6.
*/
@Mapper
public interface ISecondDao {
@Select("select * from t_test")
Test secondTest();
}
测试
至此,多数据源已经配置完毕,需要注意的点就是配置了,basePackage路径文件的创建,sqlSessionFactory和sqlSessionTemplate的注入引用问题。好了,现在我们来测试一下。
package com.example.demo.controller;
import com.example.demo.primary.IPrimaryDao;
import com.example.demo.second.ISecondDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* Created by 神烦 on 2019/9/6.
*/
@RestController
public class MoreDataSourceController {
private static Logger logger = LoggerFactory.getLogger(MoreDataSourceController.class);
@Resource
private IPrimaryDao primaryDao;
@Resource
private ISecondDao secondDao;
@RequestMapping("/test")
public Object test() {
logger.info(primaryDao.PrimaryTest().toString());
logger.info(secondDao.secondTest().toString());
return "ok";
}
}
测试结果:
2019-09-07 14:35:47.190 INFO 5812 --- [ main] .e.d.AccessingMultiDataSourceApplication : Starting AccessingMultiDataSourceApplication on USER-20180705XA with PID 5812 (D:\seestech\accessingMoreDataSource\target\classes started by 神烦 in D:\seestech\accessingMoreDataSource)
2019-09-07 14:35:47.193 INFO 5812 --- [ main] .e.d.AccessingMultiDataSourceApplication : No active profile set, falling back to default profiles: default
2019-09-07 14:35:48.324 INFO 5812 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-09-07 14:35:48.350 INFO 5812 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-09-07 14:35:48.351 INFO 5812 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.22]
2019-09-07 14:35:48.482 INFO 5812 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-09-07 14:35:48.482 INFO 5812 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1226 ms
2019-09-07 14:35:49.034 INFO 5812 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-07 14:35:49.235 INFO 5812 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-09-07 14:35:49.238 INFO 5812 --- [ main] .e.d.AccessingMultiDataSourceApplication : Started AccessingMultiDataSourceApplication in 2.778 seconds (JVM running for 3.254)
2019-09-07 14:36:05.009 INFO 5812 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-09-07 14:36:05.009 INFO 5812 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-09-07 14:36:05.014 INFO 5812 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2019-09-07 14:36:05.052 INFO 5812 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-09-07 14:36:05.289 INFO 5812 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-09-07 14:36:05.341 INFO 5812 --- [nio-8080-exec-2] c.e.d.c.MoreDataSourceController : Test(id=99999, name=主库, remark=主库数据库)
2019-09-07 14:36:05.341 INFO 5812 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
2019-09-07 14:36:05.474 INFO 5812 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
2019-09-07 14:36:05.489 INFO 5812 --- [nio-8080-exec-2] c.e.d.c.MoreDataSourceController : Test(id=99999, name=从库, remark=从库数据库)
看可能不是很清楚,照着上面的思路自己搞一下会明白很多,数据库得用自己的咯,我给置空了。
源码下载地址: github.com/Liyinzuo/ac…
如果有错误需要改正地方欢迎指正,谢谢~