很多场景下都会使用到一个工程连接多个数据库,如读写分离,分表等场景。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.meihaocloud</groupId> <artifactId>springboot_multi_datasource</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringbootMultiDatasource</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version> </plugin> </plugins> </build> </project>
默认会导入maven-resources-plugin ,但maven-resources-plugin 默认导入的是3.2.0 ,导致启动报错,原因不明(也可能是springboot版本太新,有一些bug),就改成3.1.0了
server.port=8080 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource mybatis.type-aliases-package=com.meihaocloud.**.domain # 数据库1 spring.datasource.sysdb.driver-class-name = com.mysql.jdbc.Driver spring.datasource.sysdb.url = jdbc:mysql://localhost:3306/sysdb?useUnicode=true&useSSL=false&characterEncoding=utf-8 spring.datasource.sysdb.username = root spring.datasource.sysdb.password = mysql # 数据库2 spring.datasource.orderdb.driver-class-name = com.mysql.jdbc.Driver spring.datasource.orderdb.url = jdbc:mysql://localhost:3306/orderdb?useUnicode=true&useSSL=false&characterEncoding=utf-8 spring.datasource.orderdb.username = root spring.datasource.orderdb.password = mysql # 数据库3 spring.datasource.userdb.driver-class-name = com.mysql.jdbc.Driver spring.datasource.userdb.url = jdbc:mysql://localhost:3306/userdb?useUnicode=true&useSSL=false&characterEncoding=utf-8 spring.datasource.userdb.username = root spring.datasource.userdb.password = mysql spring.datasource.initialSize=1 spring.datasource.minIdle=2 spring.datasource.maxActive=10 spring.datasource.maxWait=60000 spring.datasource.timeBetweenEvictionRunsMillis=60000 spring.datasource.minEvictableIdleTimeMillis= 300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false spring.datasource.poolPreparedStatements=true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 spring.datasource.filters = stat,wall,log4j spring.datasource.maxPoolPreparedStatementPerConnectionSize = 10 spring.datasource.useGlobalDataSourceStat = true spring.datasource.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 spring.datasource.logSlowSql=true
3个数据库,每个数据库中一个测试的表,t_user , t_order , t_sysconfig
package com.meihaocloud.springboot_multi_datasource.config; import com.alibaba.druid.pool.DruidDataSource; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; @Configuration @MapperScan(basePackages = "com.meihaocloud.springboot_multi_datasource.mapper.sys", sqlSessionTemplateRef = "sysdbSqlSessionTemplate") public class SysdbDataSourceConfig { @Bean(name = "sysdbDataSource") @ConfigurationProperties(prefix = "spring.datasource.sysdb") public DataSource setDataSource() { return new DruidDataSource(); } @Bean(name = "sysdbTransactionManager") public DataSourceTransactionManager setTransactionManager(@Qualifier("sysdbDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "sysdbSqlSessionFactory") public SqlSessionFactory setSqlSessionFactory(@Qualifier("sysdbDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/sysdb/*.xml")); return bean.getObject(); } @Bean(name = "sysdbSqlSessionTemplate") public SqlSessionTemplate setSqlSessionTemplate( @Qualifier("sysdbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
package com.meihaocloud.springboot_multi_datasource.config; import com.alibaba.druid.pool.DruidDataSource; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; @Configuration @MapperScan(basePackages = "com.meihaocloud.springboot_multi_datasource.mapper.user", sqlSessionTemplateRef = "userdbSqlSessionTemplate") public class UserdbDataSourceConfig { @Bean(name = "userdbDataSource") @ConfigurationProperties(prefix = "spring.datasource.userdb") public DataSource setDataSource() { return new DruidDataSource(); } @Bean(name = "userdbTransactionManager") public DataSourceTransactionManager setTransactionManager(@Qualifier("userdbDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "userdbSqlSessionFactory") public SqlSessionFactory setSqlSessionFactory(@Qualifier("userdbDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //如果mapper.xml和mapper接口在同一包下,下面代码就可以不用配置 bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/userdb/*.xml")); return bean.getObject(); } @Bean(name = "userdbSqlSessionTemplate") public SqlSessionTemplate setSqlSessionTemplate( @Qualifier("userdbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
package com.meihaocloud.springboot_multi_datasource.config; import com.alibaba.druid.pool.DruidDataSource; 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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; @Configuration @MapperScan(basePackages = "com.meihaocloud.springboot_multi_datasource.mapper.order", sqlSessionTemplateRef = "orderdbSqlSessionTemplate") public class OrderdbDataSourceConfig { @Bean(name = "orderdbDataSource") @ConfigurationProperties(prefix = "spring.datasource.orderdb") public DataSource setDataSource() { return new DruidDataSource(); } @Bean(name = "orderdbTransactionManager") public DataSourceTransactionManager setTransactionManager(@Qualifier("orderdbDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "orderdbSqlSessionFactory") public SqlSessionFactory setSqlSessionFactory(@Qualifier("orderdbDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //如果mapper.xml和mapper接口在同一包下,下面代码就可以不用配置 bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/orderdb/*.xml")); return bean.getObject(); } @Bean(name = "orderdbSqlSessionTemplate") public SqlSessionTemplate setSqlSessionTemplate( @Qualifier("orderdbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
如果多个数据源启动有冲突报错,需要配置@Primary
启动类是自动生成的,没做改变
import com.meihaocloud.springboot_multi_datasource.config.OrderdbDataSourceConfig; import com.meihaocloud.springboot_multi_datasource.config.SysdbDataSourceConfig; import com.meihaocloud.springboot_multi_datasource.config.UserdbDataSourceConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication public class SpringbootMultiDatasourceApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMultiDatasourceApplication.class, args); } }
Mapper.java和Mapper.xml 都是用Mybatis-Generator生成的,具体参考Mybatis逆向生成工具
Mapper分包很重要,上面数据源配置时,配置了对应Mapper.java和Mapper.xml的扫描路径
controller和service都很简单,就是根据ID查询数据