目录
- 背景
- 技术选型
- 配置多数据源思路(以两个为例)
- 代码实现
- 1.导入依赖
- 2.各自的配置
- 3.各自的dataSource
- news数据库的
- smbms数据库的
- 注意:@Primary注解
- 4.各自的SqlSessionFactory等
- news数据库的
- smbms数据库的
- 5.去掉启动类头上的@MapperScan
- 6.各自的mapper接口
- 7.各自的mapper.xml
- 8.测试
背景
- 在单数据源的情况下,Spring Boot的配置非常简单,只需要在application.properties文件中配置连接参数即可。
- 但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源
技术选型
- SpringBoot2.3.12
- jdk1.8
- mysql5.7
- 持久层框架mybatis
配置多数据源思路(以两个为例)
- 要执行两个数据库的操作,就需要有两个数据库配置
- 有两个数据库配置那就要两个SqlSessionBuilder来创建SqlSessionFactory
- 有两个SqlSessionFactory就能创建两个数据库自己的sqlSession
- 然后就能执行不同数据库的操作了
- 现在用的都是数据库连接池,需要创建dataSource,因此,按照上面的思路,也需要有各自数据库的dataSource
- 用各自的dataSource创建各自的SqlSessionFactory
- 继而创建各自的SqlSessionTemplate
- 当然,事务管理器也应该是用各自的dataSource来创建
- 那么,各自的SqlSessionFactory就要扫描各自的mapper层,因此就需要有各自的mapper包
- 至于各自的mapper.xml可以放在一起,也可以不放在一起,因为mapper.xml中的namespace是根据包名来映射的
代码实现
1.导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!-- 阿里数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.9</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency>
2.各自的配置
server:port: 8888logging:level:org.springframework.web: debugcom.kgc.mapper: debug
spring:datasource:smbms:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456news:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/chinanewsdb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis:mapper-locations: classpath:mybatis/mapper/*.xmltype-aliases-package: com.kgc.pojonews:mapper-locations: classpath:mybatis/newsmapper/*.xml
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.各自的dataSource
news数据库的
package com.kgc.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
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 javax.sql.DataSource;/*** @author: zjl* @datetime: 2024/4/20* @desc:*/
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.news")
public class NewsDataSourceConfig {@Value("${spring.datasource.news.driverClassName}")private String driverClassName;@Value("${spring.datasource.news.url}")private String url;@Value("${spring.datasource.news.username}")private String username;@Value("${spring.datasource.news.password}")private String password;@Bean("newsDataSource")public DataSource createDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
smbms数据库的
package com.kgc.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
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 javax.sql.DataSource;/*** @author: zjl* @datetime: 2024/4/20* @desc:*/
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.smbms")
public class SmbmsDataSourceConfig {@Value("${spring.datasource.smbms.driverClassName}")private String driverClassName;@Value("${spring.datasource.smbms.url}")private String url;@Value("${spring.datasource.smbms.username}")private String username;@Value("${spring.datasource.smbms.password}")private String password;@Bean("smbmsDataSource")@Primarypublic DataSource createDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
注意:@Primary注解
- 其作用与功能,当有多个相同类型的bean时,使用@Primary来赋予bean更高的优先级。
- 在这里,需要注册多个相同DataSource类型的bean,要有一个有更高的优先级,否则会报错
4.各自的SqlSessionFactory等
news数据库的
package com.kgc.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.beans.factory.annotation.Value;
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 org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;
import javax.sql.DataSource;/*** @author: zjl* @datetime: 2024/4/20* @desc:*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.news.mapper",sqlSessionFactoryRef = "newsSqlSessionFactory")
public class NewsSqlSessionFactoryConfiguratiion {@Resource(name = "newsDataSource")private DataSource newsDataSource;@Value("${mybatis.news.mapper-locations}")private String mapperLocations;@Bean("newsSqlSessionFactory")public SqlSessionFactory create() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(newsDataSource);PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));return bean.getObject();}@Bean("newsSqlSessionTemplate")public SqlSessionTemplate createSqlSession(@Qualifier("newsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Bean("newsTransactionManager")public PlatformTransactionManager createTransactionManager(){return new DataSourceTransactionManager(newsDataSource);}
}
smbms数据库的
package com.kgc.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.beans.factory.annotation.Value;
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 org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;/*** @author: zjl* @datetime: 2024/4/20* @desc:*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.mapper",sqlSessionFactoryRef = "smbmsSqlSessionFactory")
public class SmbmsSqlSessionFactoryConfiguratiion {@Resource(name = "smbmsDataSource")private DataSource smbmsDataSource;@Value("${mybatis.mapper-locations}")private String mapperLocations;@Bean("smbmsSqlSessionFactory")public SqlSessionFactory create() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(smbmsDataSource);PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));return bean.getObject();}@Bean("smbmsSqlSessionTemplate")public SqlSessionTemplate createSqlSession(@Qualifier("smbmsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}@Bean("smbmsTransactionManager")public PlatformTransactionManager createTransactionManager(){return new DataSourceTransactionManager(smbmsDataSource);}
}
5.去掉启动类头上的@MapperScan
@SpringBootApplication
//@MapperScan(basePackages = {"com.kgc.mapper"})
public class BootdemoApplication {public static void main(String[] args) {SpringApplication.run(BootdemoApplication.class, args);}
}
6.各自的mapper接口
public interface UserMapper {int selectCount();
}
public interface NewsMapper {int selectCount();
}
7.各自的mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.mapper.UserMapper"><select id="selectCount" resultType="int">SELECT COUNT(1) FROM SMBMS_USER</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.news.mapper.NewsMapper"><select id="selectCount" resultType="int">SELECT COUNT(1) FROM news_detail</select>
</mapper>
8.测试
service
@Service
public class UserService {@Resourceprivate UserMapper userMapper;@Resourceprivate NewsMapper newsMapper;public Integer allCount(){return userMapper.selectCount() + newsMapper.selectCount();}
}
controller
@RestController
public class UserController {@Resourceprivate UserService userService;@RequestMapping("/all")public Object all(){return userService.allCount();}
}