1. 什么是多数据源? 所谓多数据源,就是一个Java EE
项目中采用了不同数据库实例中的多个库,或者同一个数据库实例中多个不同的库。一般来说,采用MyCat
等分布式数据库中间件是比较好的解决方案,这样可以把数据库读写分离、分库分表、备份等操作交给中间件去做,Java
代码只需要专注于业务即可。不过,这并不意味着无法使用Java
代码解决类似的问题,在Spring Framework
中就可以配置多数据源,Spring Boot
继承其衣钵,只不过配置方式有所变化。
2. 准备数据 2.1 创建数据库和表 1.创建数据库db1和表student CREATE DATABASE db1;CREATE TABLE `db1`.`student` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id' , `name` varchar (20 ) NOT NULL DEFAULT '' COMMENT '名称' , `schoolId` int DEFAULT NULL COMMENT '学校ID' , PRIMARY KEY (`id`) ) ENGINE= InnoDB AUTO_INCREMENT= 2 DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT= '学生表' ;INSERT INTO `db1`.`student`(`name`,`schoolId`)VALUES ('小明' ,100 );
2.创建数据库db2和表test2 CREATE DATABASE db2;CREATE TABLE `db2`.`school` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '学校id' , `name` varchar (20 ) NOT NULL DEFAULT '' COMMENT '学校名称' , `address` varchar (255 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE= InnoDB COMMENT= '学校表' ;INSERT INTO `db2`.`school`(`id`,`name`,`address`)VALUES (100 ,'北京大学' ,'北京' );
2.2 创建实体类 1. 新建学生实体类 新建文件: StudentModel.java
文件位置: src/main/java/com/hui/javalearn/model/db1/StudentModel.java
代码如下:
package com.hui.javalearn.model.db1;import lombok.Data;@Data public class StudentModel { private Integer id; private String name; private Integer schoolId; }
2. 新建学校实体类 新建文件: SchoolModel.java
文件位置: src/main/java/com/hui/javalearn/model/db2/SchoolModel.java
代码如下:
package com.hui.javalearn.model.db2;import lombok.Data;@Data public class SchoolModel { private Integer id; private String name; private String address; }
2.3 创建学生Dao和Mapper文件 1.创建学生Dao 新建文件: StudentDao.java
文件位置: src/main/java/com/hui/javalearn/dao/db1/StudentDao.java
代码如下:
package com.hui.javalearn.dao.db1;import com.hui.javalearn.model.db1.StudentModel;public interface StudentDao { StudentModel getStudent (Integer id) ; }
2.创建学生Mapper 新建文件: StudentMapper.xml
文件位置: java-learn/src/main/resources/mapper/db1/StudentMapper.xml
代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.hui.javalearn.dao.db1.StudentDao" > <select id ="getStudent" resultType ="com.hui.javalearn.model.db1.StudentModel" parameterType ="java.lang.Integer" > select * from student where id = #{id,jdbcType=INTEGER} </select > </mapper >
2.4 创建学校Dao和Mapper文件 1.创建学校Dao 新建文件: SchoolDao.java
文件位置: src/main/java/com/hui/javalearn/dao/db2/SchoolDao.java
代码如下:
package com.hui.javalearn.dao.db2;import com.hui.javalearn.model.db2.SchoolModel;public interface SchoolDao { SchoolModel getSchoolById (Integer id) ; }
2.创建学校Mapper 新建文件: SchoolMapper.xml
文件位置: java-learn/src/main/resources/mapper/db2/SchoolMapper.xml
代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.hui.javalearn.dao.db2.SchoolDao" > <select id ="getSchoolById" parameterType ="integer" resultType ="com.hui.javalearn.model.db2.SchoolModel" > select * from school where id = #{id,jdbcType=INTEGER} </select > </mapper >
3.引入依赖 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.1.2</version > </dependency >
4.配置数据库连接 修改配置文件: application.yml
文件位置: src/main/resources/application.yml
代码如下:
server: port: 8080 spring: datasource: one: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?useSSL=false two: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root jdbc-url: jdbc:mysql://127.0.0.1:3306/db2?useSSL=false logging: level: com.hui.javalearn.dao: debug
5.配置数据源 5.1 配置名为One数据源 新建文件: MybatisDataSourceOneConfig.java
文件位置: src/main/java/com/hui/javalearn/config/MybatisDataSourceOneConfig.java
代码如下:
package com.hui.javalearn.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.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.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;@Configuration @MapperScan(basePackages = "com.hui.javalearn.dao.db1", sqlSessionFactoryRef = "testOneSqlSessionFactory") public class MybatisDataSourceOneConfig { @Bean(name = "dbOne") @ConfigurationProperties(prefix = "spring.datasource.one") public DataSource testOneDataSource () { return DataSourceBuilder.create().build(); } @Bean(name = "testOneSqlSessionFactory") public SqlSessionFactory testOneSqlSessionFactory (@Qualifier("dbOne") DataSource dbOneDataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dbOneDataSource); Resource[] mapperXmlResources = new PathMatchingResourcePatternResolver ().getResources("classpath:mapper/db1/*.xml" ); sqlSessionFactoryBean.setMapperLocations(mapperXmlResources); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate testOneSqlSessionTemplate ( @Qualifier("testOneSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate (sqlSessionFactory); } }
5.2 配置名为Two数据源 新建文件: MybatisDataSourceTwoConfig.java
文件位置: src/main/java/com/hui/javalearn/config/MybatisDataSourceTwoConfig.java
代码如下:
package com.hui.javalearn.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.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.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;@Configuration @MapperScan(basePackages = "com.hui.javalearn.dao.db2", sqlSessionFactoryRef = "testTwoSqlSessionFactory") public class MybatisDataSourceTwoConfig { @Bean(name = "dbTwo") @ConfigurationProperties(prefix = "spring.datasource.two") public DataSource testTwoDataSource () { return DataSourceBuilder.create().build(); } @Bean(name = "testTwoSqlSessionFactory") public SqlSessionFactory testTwoSqlSessionFactory (@Qualifier("dbTwo") DataSource dbOneDataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean (); sqlSessionFactoryBean.setDataSource(dbOneDataSource); Resource[] mapperXmlResources = new PathMatchingResourcePatternResolver ().getResources("classpath:mapper/db2/*.xml" ); sqlSessionFactoryBean.setMapperLocations(mapperXmlResources); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate testTwoSqlSessionTemplate ( @Qualifier("testTwoSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate (sqlSessionFactory); } }
6.文件位置总览
7.测试 新建测试文件: TestMultiDataSource.java
文件位置: src/test/java/com/hui/javalearn/TestMultiDataSource.java
package com.hui.javalearn;import com.hui.javalearn.dao.db1.StudentDao;import com.hui.javalearn.dao.db2.SchoolDao;import com.hui.javalearn.model.db1.StudentModel;import com.hui.javalearn.model.db2.SchoolModel;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;@SpringBootTest public class TestMultiDataSource { @Resource private StudentDao testOneDao; @Resource private SchoolDao schoolDao; @Test void run () { StudentModel studentModel = testOneDao.getStudent(1 ); Integer schoolId = studentModel.getSchoolId(); SchoolModel schoolModel = schoolDao.getSchoolById(schoolId); String res = "学生ID: " + studentModel.getId() + " 名字: " + studentModel.getName() + " 学校: " + schoolModel.getName() + " 学校地址: " + schoolModel.getAddress(); System.out.println(res); } }