前言
之前编写了一篇maven项目创建多数据库的方法,现在对springboot更了解之后,将把springboot项目配置多数据库的方法贴出来。
从项目开始创建到调用数据库依次写出来。
PS:本项目使用的是IDEA进行创建
创建springboot项目
1.点击创建新maven项目,然后下一步
2.输入项目名称,创建项目
3.创建完成之后,初始默认结构如下:
需要创建的文件夹结构分类
以下截图为进行不同功能分类进行创建的文件夹
文件说明:
java文件都应该在java文件夹下
资源文件都应该放在resources下
bean: 存放实体对象
controller:存放控制层
service: 存放service层
db: 多数据库配置
mapper:数据库连接接口
tools:工具类
resources/mapper数据库的增删改查文件
以下为为配置多数据库应创建的文件,文件截图和说明如下:
java文件都应该在java文件夹下
资源文件都应该放在resources下
db: db文件夹下的文件为多数据库配置代码
mapper:com.mapper下的文件为编写数据库的增删改查方法
MultipleDataApplication.java:启动类
resources/mapper下的文件数据库的增删改查`语句`文件
其中
resources/mapper下的MyDb1为对应数据库MyDb1的编写数据库语句文件
resources/mapper下的MyDb2为对应数据库MyDb2的编写数据库语句文件
applition.yml:springboot项目配置文件
pom.xml:依赖配置文件
导入pom依赖
初始pom.xml配置文件代码为:
要完成多数据库配置,需要至少导入以下依赖:
第一个:springboot依赖
第二个:mybatis
第三个:数据库驱动依赖
第四个: 阿里巴巴数据库连接池
pom.xml代码如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>multipleDataConnection</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- springboot管理配置-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<dependencies>
<!-- springboot依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</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-web</artifactId>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
编写配置xml(yml)
在项目配置信息,需要编写启动端口,数据库连接以及连接池和mybatis的配置信息
具体配置信息如下:
以下为application.yml格式配置文件代码
server:
port: 9021
servlet:
context-path: /启动路径
# 数据库
spring:
datasource:
MyDb1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://数据库ip:3306/数据库名
username: 用户名
password: 密码
MyDb2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://数据库ip:3306/数据库名
username: 用户名
password: 密码
druid:
#最大活跃数
maxActive: 20
#初始化数量
initialSize: 1
#最大连接等待超时时间
maxWait: 60000
#打开PSCache,并且指定每个连接PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
#通过connectionProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 1 from dual
validationQuery1: select 1
# 注意 有的数据库不支持select 1 from dual 在配置处需要修改为下方的select 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
filters: stat, wall, log4j
# 合并多个DruidDataSource的监控数据
use-global-data-source-stat: true
mybatis:
configuration:
map-underscore-to-camel-case: true
# 全局的sql执行超时时间(单位s) 当sql执行时间超过1s,就会断开操作了,起到保护数据库服务的作用
default-statement-timeout: 5
# 流式
default-fetch-size: 100
# 配置查询返回最大数量
max_row: 10000
注意: spring下的datasource,为编写多个数据库的连接信息,ip账号密码等。
其中作为演示,我把两个数据库名称分别标注命名为MyDb1和MyDb2
validationQuery:为验证不同的数据库连接的语句,不同数据库的验证语句不同
不同数据库验证语句如下:
数据库
validationQuery验证语句
hsqldb
select 1 from INFORMATION_SCHEMA.SYSTEM_USERS
Oracle
select 1 from dual
DB2
select 1 from sysibm.sysdummy1
MySql
select 1
Microsoft SqlServer
select 1
postgresql
select version()
ingres
select 1
derby
select 1
H2
select 1
这个验证连接语句需要根据自己连的数据库进行更改配置语句
编写resource的mapper查询
在resource/mapper里,我创建了两个文件MyDb1Mapper.xml
和MyDb2Mapper.xml
,用来标识两个不同数据库的连接的文件.
其中MyDb1Mapper.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.mapper.MyDb1.MyDb1Mapper">
</mapper>
其中MyDb2Mapper.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.mapper.MyDb2.MyDb2Mapper">
</mapper>
注意:此处`namespace`路径为数据库接口文件路径
编写mapper接口
在com.demo.mapper下有两个文件夹,分别标识不同的数据库接口文件,
其中mapper/MyDb1Mapper.java
文件代码如下(不包含功能):
package com.mapper.MyDb1;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MyDb1Mapper {
}
其中mapper/MyDb2Mapper.java
文件代码如下(不包含功能):
package com.mapper.MyDb2;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MyDb2Mapper {
}
名称随便命名,自己容易区别就行
编写多数据库配置
如你所见,在上方截图中我编写了四个文件作为数据库配置,如你需要根据它去删除或添加多个数据库,把里面的DbMyDb1Config
和DbMyDb2Config
换成你自己的数据库配置即可(根据yml里,你数据库的配置修改)
同时,在DataSourceConfig里增减需要的数据库配置代码,复制修改名称即可
MybatisInterceptor不需要修改。
如果有更多的数据库需要连接进来,只需要在`DataSourceConfig`里添加新数据库的配置代码,复制
`DbMyDb1Config`和`DbMyDb2Config`其中一个文件进行修改DataSourceConfig对应名称配置即可
其中,DataSourceConfig
代码如下:
package com.db;
import com.alibaba.druid.pool.DruidDataSource;
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 javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.MyDb1.driver-class-name}")
private String MyDb1Driver;
@Value("${spring.datasource.MyDb1.url}")
private String MyDb1Url;
@Value("${spring.datasource.MyDb1.username}")
private String MyDb1Username;
@Value("${spring.datasource.MyDb1.password}")
private String MyDb1Password;
@Value("${spring.datasource.MyDb2.driver-class-name}")
private String MyDb2Driver;
@Value("${spring.datasource.MyDb2.url}")
private String MyDb2Url;
@Value("${spring.datasource.MyDb2.username}")
private String MyDb2Username;
@Value("${spring.datasource.MyDb2.password}")
private String MyDb2Password;
@Value("${spring.datasource.druid.maxActive}")
private Integer maxActive;
@Value("${spring.datasource.druid.initialSize}")
private Integer initialSize;
@Value("${spring.datasource.druid.maxWait}")
private Integer maxWait;
@Value("${spring.datasource.druid.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize}")
private Integer maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.druid.minIdle}")
private Integer minIdle;
@Value("${spring.datasource.druid.connectionProperties}")
private String connectionProperties;
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
private Integer timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
private Integer minEvictableIdleTimeMillis;
@Value("${spring.datasource.druid.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.druid.validationQuery1}")
private String validationQuery1;
@Value("${spring.datasource.druid.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.druid.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.druid.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.druid.filters}")
private String filters;
@Value("${spring.datasource.druid.use-global-data-source-stat}")
private boolean useGlobalDataSourceStat;
@Bean(name = "dsMyDb1")
@Qualifier("dsMyDb1")
public DataSource dataSourceMyDb1() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(MyDb1Url);
datasource.setUsername(MyDb1Username);
datasource.setPassword(MyDb1Password);
datasource.setDriverClassName(MyDb1Driver);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
// try {
// datasource.setFilters(filters);
// } catch (SQLException e) {
// System.err.println("druid configuration initialization filter: " + e);
// }
datasource.setConnectionProperties(connectionProperties);
datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
return datasource;
}
@Bean(name = "dsMyDb2")
@Qualifier("dsMyDb2")
public DataSource dataSourceMyDb2() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(MyDb2Url);
datasource.setUsername(MyDb2Username);
datasource.setPassword(MyDb2Password);
datasource.setDriverClassName(MyDb2Driver);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
// try {
// datasource.setFilters(filters);
// } catch (SQLException e) {
// System.err.println("druid configuration initialization filter: " + e);
// }
datasource.setConnectionProperties(connectionProperties);
datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
return datasource;
}
}
其中MybatisInterceptor
代码如下:
package com.db;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
@Intercepts({@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MybatisInterceptor implements Interceptor {
@Value("${mybatis.max_row}")
private Integer max_row;
@Override
public Object intercept(Invocation invocation) throws Throwable {
invocation.getArgs()[2] = new RowBounds(0, (null == max_row || 0 == max_row) ? 10000 : max_row);
return invocation.proceed();
}
@Override
public Object plugin(Object o) {
return Plugin.wrap(o, this);
}
@Override
public void setProperties(Properties properties) {
}
}
其中DbMyDb1Config
代码如下:
package com.db;
import org.apache.ibatis.plugin.Interceptor;
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 org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = {"com.mapper.MyDb1"}, sqlSessionFactoryRef = "SqlSessionFactoryMyDb1")
public class DbMyDb1Config {
@Autowired
private MybatisInterceptor mybatisInterceptor;
@Resource
@Qualifier("dsMyDb1")
private DataSource dsMyDb1;
/**
* 创建sqlsessionfactory
*/
@Bean(name = {"SqlSessionFactoryMyDb1"})
@Primary
public SqlSessionFactory sqlSessionFactoryMyDb1() throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dsMyDb1);
org.springframework.core.io.Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/MyDb1/*.xml");
sessionFactoryBean.setMapperLocations(resources);
sessionFactoryBean.setPlugins(new Interceptor[]{mybatisInterceptor});
return sessionFactoryBean.getObject();
}
@Bean(name = {"dbMyDb1TransactionManager"})
@Primary
public DataSourceTransactionManager dbMyDb1TransactionManager(@Qualifier("dsMyDb1") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@Primary
public SqlSessionTemplate dbMyDb1SqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryMyDb1());
}
}
其中DbMyDb2Config
代码如下
package com.db;
import org.apache.ibatis.plugin.Interceptor;
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 org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = {"com.Invoice.mapper.MyDb2"}, sqlSessionFactoryRef = "SqlSessionFactoryMyDb2")
public class DbMyDb2Config {
@Autowired
private MybatisInterceptor mybatisInterceptor;
@Resource
@Qualifier("dsMyDb2")
private DataSource dsMyDb2;
/**
* 创建sqlsessionfactory
*/
@Bean(name = {"SqlSessionFactoryMyDb2"})
public SqlSessionFactory sqlSessionFactoryMyDb2() throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dsMyDb2);
org.springframework.core.io.Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/MyDb2/*.xml");
sessionFactoryBean.setMapperLocations(resources);
sessionFactoryBean.setPlugins(new Interceptor[]{mybatisInterceptor});
return sessionFactoryBean.getObject();
}
@Bean(name = {"dbMyDb2TransactionManager"})
public DataSourceTransactionManager dbMyDb2TransactionManager(@Qualifier("dsMyDb2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SqlSessionTemplate dbMyDb2SqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryMyDb2());
}
}
注意:
MyDb1Config和MyDb2Config的代码有一个很重要的区别,必须有且只有一个数据库作为主数据库。
用注解@primary标注
可以仔细看MyDb1Config和MyDb2Config的这个区别,他们的区别就在于@primary
启动类
Application.java启动类代码如下:
package com;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* description: 启动类
* */
@SpringBootApplication
@MapperScan("com.mapper")
public class MultipleDataApplication {
public static void main(String[] args) {
SpringApplication.run(MultipleDataApplication.class,args);
}
}
运行成功截图
异常处理
在连接某些数据库,可能会出现一些异常,如写了接口方法找不到、但确实有写;如hana的时候遇到一个找不到对应的表,但是确实是有这个表在数据库,可以尝试简化DataSourceConfig
的各个数据库配置
以下代码为最原始简单的连接数据库的配置,加上阿里巴巴连接池的目的是为了优化数据库连接
所有的数据库连接配置都可以用以下的代码配置
@Bean(name = "dsDemo")
@Qualifier("dsDemo")
public DataSource dataSourceErp() {
return DataSourceBuilder.create()
.type(DruidDataSource.class)
.driverClassName(DemoDriver)
.url(DemopUrl)
.username(DemoUsername)
.password(DemoPassword)
.build();
}
结语
以上基于springboot多数据库连接的项目我是重新新建项目后一步步验证后发出来的。测试有效。
如果后续有更完善的内容,将会在这边进行更新出来。
希望能帮助到大家。