主从数据源的配置:
1:首先搭建一个SpringBoot的项目工程,这里就不在演示搭建。
2:mysql的数据库中准备两个数据库,db1和db2
3:如下指引,开始进行相关的项目配置
搭建一个SpringBoot的项目,完整的目录结构如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</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>
</dependencies>
进行多数据源的配置
1:在目录下的config下创建:DataSourceConfigOne:主数据源配置类
package org.example.adminmanage.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.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
* @program: mry
* @description: 多数据源的配置--主数据源
* @author: 城南的夏
* @create: 2020-12-19 18:50
**/
@Configuration
@MapperScan(basePackages = "org.example.adminmanage.dao.db1",sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSourceConfigOne {
// 表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
@Primary
@Bean("db1DataSource")
//读取application.yml中的配置参数映射成为一个对象
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource getDataSourceOne() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean("db1SqlSessionFactory")
public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//db1的Mapper文件的位置
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:**/mapper1/*.xml"));
return bean.getObject();
}
@Primary
@Bean("db1SqlSessionTemplate")
public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
2:在目录下的config下创建:DataSourceConfigTwo:主数据源配置类(参考图一的项目目录结构)
package org.example.adminmanage.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.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
* @program: mry
* @description: 多数据源的配置--次数据源
* @author: 城南的夏
* @create: 2020-12-19 18:50
**/
@Configuration
@MapperScan(basePackages = "org.example.adminmanage.dao.db2",sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DataSourceConfigTwo {
// 表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
@Bean("db2DataSource")
//读取application.yml中的配置参数映射成为一个对象
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource getDataSourceOne() {
return DataSourceBuilder.create().build();
}
@Bean("db2SqlSessionFactory")
public SqlSessionFactory db2SqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//db1的Mapper文件的位置
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:**/mapper2/*.xml"));
return bean.getObject();
}
@Bean("db2SqlSessionTemplate")
public SqlSessionTemplate db2SqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
建目录dao层 —(参考图一的项目目录结构)
db1:代码结构
package org.example.adminmanage.dao.db1;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.example.adminmanage.entity.One;
import java.util.List;
/**
* (One)表数据库访问层
*
* @author makejava
* @since 2020-12-19 19:47:49
*/
public interface OneDao extends BaseMapper<One> {
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
One queryById(Integer id);
/**
* 查询指定行数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<One> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);
/**
* 通过实体作为筛选条件查询
*
* @param one 实例对象
* @return 对象列表
*/
List<One> queryAll(One one);
/**
* 新增数据
*
* @param one 实例对象
* @return 影响行数
*/
int insert(One one);
/**
* 修改数据
*
* @param one 实例对象
* @return 影响行数
*/
int update(One one);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 影响行数
*/
int deleteById(Integer id);
List<One> query();
}
db2:代码结构 ----(参考图一的项目目录结构)
package org.example.adminmanage.dao.db2;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.example.adminmanage.entity.Two;
import java.util.List;
/**
* (Two)表数据库访问层
*
* @author makejava
* @since 2020-12-19 19:41:33
*/
//@DS("db2")
public interface TwoDao extends BaseMapper<Two> {
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
Two queryById(Integer id);
/**
* 查询指定行数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<Two> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);
/**
* 通过实体作为筛选条件查询
*
* @param two 实例对象
* @return 对象列表
*/
List<Two> queryAll(Two two);
/**
* 新增数据
*
* @param two 实例对象
* @return 影响行数
*/
int insert(Two two);
/**
* 修改数据
*
* @param two 实例对象
* @return 影响行数
*/
int update(Two two);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 影响行数
*/
int deleteById(Integer id);
List<Two> query();
}
新建 entity 目录 ----(参考图一的项目目录结构)
One 实体类
package org.example.adminmanage.entity;
import java.io.Serializable;
/**
* (One)实体类
*
* @author makejava
* @since 2020-12-19 19:47:49
*/
public class One implements Serializable {
private static final long serialVersionUID = 959029700988159827L;
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Two 实体
package org.example.adminmanage.entity;
import java.io.Serializable;
/**
* (Two)实体类
*
* @author makejava
* @since 2020-12-19 19:41:33
*/
public class Two implements Serializable {
private static final long serialVersionUID = 725826958790784302L;
private Integer id;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
新建目录service层 ----(参考图一的项目目录结构)
package org.example.adminmanage.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.example.adminmanage.entity.One;
import java.util.List;
/**
* (One)表服务接口
*
* @author makejava
* @since 2020-12-19 19:47:49
*/
public interface OneService extends IService<One> {
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
One queryById(Integer id);
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<One> queryAllByLimit(int offset, int limit);
/**
* 新增数据
*
* @param one 实例对象
* @return 实例对象
*/
One insert(One one);
/**
* 修改数据
*
* @param one 实例对象
* @return 实例对象
*/
One update(One one);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
boolean deleteById(Integer id);
List<One> queryAll();
}
package org.example.adminmanage.service;
import org.example.adminmanage.entity.Two;
import java.util.List;
/**
* (Two)表服务接口
*
* @author makejava
* @since 2020-12-19 19:41:33
*/
public interface TwoService {
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
Two queryById(Integer id);
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List<Two> queryAllByLimit(int offset, int limit);
/**
* 新增数据
*
* @param two 实例对象
* @return 实例对象
*/
Two insert(Two two);
/**
* 修改数据
*
* @param two 实例对象
* @return 实例对象
*/
Two update(Two two);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
boolean deleteById(Integer id);
List<Two> queryAll();
}
package org.example.adminmanage.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.adminmanage.entity.One;
import org.example.adminmanage.dao.db1.OneDao;
import org.example.adminmanage.service.OneService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* (One)表服务实现类
*
* @author makejava
* @since 2020-12-19 19:47:49
*/
@Service("oneService")
public class OneServiceImpl extends ServiceImpl<OneDao, One> implements OneService {
@Resource
private OneDao oneDao;
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
@Override
public One queryById(Integer id) {
return this.oneDao.queryById(id);
}
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
@Override
public List<One> queryAllByLimit(int offset, int limit) {
return this.oneDao.queryAllByLimit(offset, limit);
}
/**
* 新增数据
*
* @param one 实例对象
* @return 实例对象
*/
@Override
public One insert(One one) {
this.oneDao.insert(one);
return one;
}
/**
* 修改数据
*
* @param one 实例对象
* @return 实例对象
*/
@Override
public One update(One one) {
this.oneDao.update(one);
return this.queryById(one.getId());
}
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
@Override
public boolean deleteById(Integer id) {
return this.oneDao.deleteById(id) > 0;
}
@Override
public List<One> queryAll() {
return oneDao.query();
}
}
package org.example.adminmanage.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Select;
import org.example.adminmanage.entity.Two;
import org.example.adminmanage.dao.db2.TwoDao;
import org.example.adminmanage.service.TwoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* (Two)表服务实现类
*
* @author makejava
* @since 2020-12-19 19:41:33
*/
@Service("twoService")
public class TwoServiceImpl implements TwoService {
@Resource
private TwoDao twoDao;
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
@Override
public Two queryById(Integer id) {
return this.twoDao.queryById(id);
}
/**
* 查询多条数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
@Override
public List<Two> queryAllByLimit(int offset, int limit) {
return this.twoDao.queryAllByLimit(offset, limit);
}
/**
* 新增数据
*
* @param two 实例对象
* @return 实例对象
*/
@Override
public Two insert(Two two) {
this.twoDao.insert(two);
return two;
}
/**
* 修改数据
*
* @param two 实例对象
* @return 实例对象
*/
@Override
public Two update(Two two) {
this.twoDao.update(two);
return this.queryById(two.getId());
}
/**
* 通过主键删除数据
*
* @param id 主键
* @return 是否成功
*/
@Override
public boolean deleteById(Integer id) {
return this.twoDao.deleteById(id) > 0;
}
@Override
@DS("db2")
@Select("select * from two")
public List<Two> queryAll() {
return twoDao.query();
}
}
mapper文件
<?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="org.example.adminmanage.dao.db1.OneDao">
<resultMap id="BaseResultMap" type="org.example.adminmanage.entity.One">
<!--@Table one-->
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
</resultMap>
<!--查询单个-->
<select id="queryById" resultMap="BaseResultMap">
select
id, name
from one
where id = #{id}
</select>
<!--查询指定行数据-->
<select id="queryAllByLimit" resultMap="BaseResultMap">
select
id, name
from one
limit #{offset}, #{limit}
</select>
<!--通过实体作为筛选条件查询-->
<select id="queryAll" resultMap="BaseResultMap">
select
id, name
from one
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="name != null and name != ''">
and name = #{name}
</if>
</where>
</select>
<select id="query" resultType="org.example.adminmanage.entity.One">
select * from one;
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into one(name)
values (#{name})
</insert>
<!--通过主键修改数据-->
<update id="update">
update one
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
</set>
where id = #{id}
</update>
<!--通过主键删除-->
<delete id="deleteById">
delete from one where id = #{id}
</delete>
</mapper>
<?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="org.example.adminmanage.dao.db2.TwoDao">
<resultMap id="BaseResultMap" type="org.example.adminmanage.entity.Two">
<!--@Table two-->
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="address" column="address" jdbcType="VARCHAR"/>
</resultMap>
<!--查询单个-->
<select id="queryById" resultMap="BaseResultMap">
select
id, address
from two
where id = #{id}
</select>
<!--查询指定行数据-->
<select id="queryAllByLimit" resultMap="BaseResultMap">
select
id, address
from two
limit #{offset}, #{limit}
</select>
<!--通过实体作为筛选条件查询-->
<select id="queryAll" resultMap="BaseResultMap">
select
id, address
from two
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="address != null and address != ''">
and address = #{address}
</if>
</where>
</select>
<select id="query" resultType="org.example.adminmanage.entity.Two">
select * from two
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into two(address)
values (#{address})
</insert>
<!--通过主键修改数据-->
<update id="update">
update two
<set>
<if test="address != null and address != ''">
address = #{address},
</if>
</set>
where id = #{id}
</update>
<!--通过主键删除-->
<delete id="deleteById">
delete from two where id = #{id}
</delete>
</mapper>
controller层目录代码
package org.example.adminmanage.controller;
import org.example.adminmanage.entity.One;
import org.example.adminmanage.service.OneService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* (One)表控制层
*
* @author makejava
* @since 2020-12-19 19:47:49
*/
@RestController
@RequestMapping("one")
public class OneController {
/**
* 服务对象
*/
@Resource
private OneService oneService;
/**
* 通过主键查询单条数据
*
* @param id 主键
* @return 单条数据
*/
@GetMapping("selectOne")
public One selectOne(Integer id) {
return this.oneService.queryById(id);
}
@GetMapping("queryOne")
public List<One> query() {
return oneService.queryAll();
}
}
package org.example.adminmanage.controller;
import org.example.adminmanage.entity.Two;
import org.example.adminmanage.service.TwoService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* (Two)表控制层
*
* @author makejava
* @since 2020-12-19 19:41:33
*/
@RestController
@RequestMapping("two")
public class TwoController {
/**
* 服务对象
*/
@Resource
private TwoService twoService;
/**
* 通过主键查询单条数据
*
* @param id 主键
* @return 单条数据
*/
@GetMapping("selectOne")
public Two selectOne(Integer id) {
return this.twoService.queryById(id);
}
@GetMapping("queryTwo")
public List<Two> query() {
return twoService.queryAll();
}
}
接下来就是yml配置文件中的配置了
server:
port: 8080
spring:
datasource:
db1:
jdbc-url: jdbc:mysql://localhost:3306/db1?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
db2:
jdbc-url: jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
durid:
initial-size: 1
max-active: 20
min-idle: 1
max-wait: 60000
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
以及入口类的配置
DruidDataSourceAutoConfigure会注入一个DataSourceWrapper,其会在原生的spring.datasource下找 url, username, password 等。动态数据源 URL 等配置是在 dynamic 下,因此需要排除,否则会报错。排除方式有两种,一种是上述配置文件排除,还有一种可以在项目启动类排除:
package org.example.adminmanage;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//在入口类的注解上添加如下的参数配置
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class AdminManageApplication {
public static void main(String[] args) {
SpringApplication.run(AdminManageApplication.class, args);
}
}
给使用非默认数据源添加注解@DS
@DS 可以注解在方法上和类上,同时存在方法注解优先于类上注解。
注解在 service 实现或 mapper 接口方法上,不要同时在 service 和 mapper 注解。
这样就完成多数据源的配置了。大家有问题的在下方留言。