SpringBoot配置多数据源Mybatis/MybatisPlus/mysql

一、前言

项目开发过程中,单一数据源不能满足开发需求或者需要用到主从数据库的时候,引入多数据源配置在项目中显得尤为必要。下面简单介绍一种在spingboot中结合mybatis针对同类型的数据源mysql进行多数据源配置和应用

环境准备:

JDK 1.8
SpringBoot 2.5.1
Maven 3.6.3
MySQL 5.7

二、目录结构

工程结构

三、引入数据库依赖

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

四、添加数据源(yml)

#数据源连接信息
spring:
  datasource:
    primary:
      username: root
      password: mima12345
      jdbc-url: jdbc:mysql://192.168.10.102:3306/mingqian?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
      driver-class-name: com.mysql.jdbc.Driver
    datasource2:
      username: root
      password: mima12345
      jdbc-url: jdbc:mysql://192.168.10.102:3306/mingqianbak?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
      driver-class-name: com.mysql.jdbc.Driver

五、添加数据源的配置文件

  • 主数据源
@Configuration
@MapperScan(basePackages = {"com.sunshine.mapper.primary"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class PrimaryDataSourceConfig {

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    @Primary
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "transactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "sqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
  • 第二数据源
@Configuration
@MapperScan(basePackages = {"com.sunshine.mapper.datasource2"}, sqlSessionFactoryRef = "sqlSessionFactory2")
public class SecondDataSourceConfig {

   @Bean(name = "dataSource2")
   @ConfigurationProperties(prefix = "spring.datasource.datasource2")
   public DataSource dataSource() {
       return DataSourceBuilder.create().build();
   }

   @Bean(name = "sqlSessionFactory2")
   public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource2") DataSource dataSource) throws Exception {
       SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
       bean.setDataSource(dataSource);
       bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
       return bean.getObject();
   }

   @Bean(name = "transactionManager2")
   public DataSourceTransactionManager transactionManager(@Qualifier("dataSource2") DataSource dataSource) {
       return new DataSourceTransactionManager(dataSource);
   }

   @Bean(name = "sqlSessionTemplate2")
   public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) {
       return new SqlSessionTemplate(sqlSessionFactory);
   }
}

六、测试

6-1:sql建表语句

-- mingqian
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for book_info :mingqian主库中的表
-- ----------------------------
DROP TABLE IF EXISTS `book_info`;
CREATE TABLE `book_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author` varchar(64) NOT NULL COMMENT '作者信息',
  `name` varchar(64) NOT NULL COMMENT '书籍名称',
  `price` decimal(10,0) NOT NULL COMMENT '价格',
  `createTime` datetime DEFAULT NULL COMMENT '上架时间',
  `description` varchar(128) DEFAULT NULL COMMENT '书籍描述',
  `updateTime` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of book_info
-- ----------------------------
INSERT INTO `book_info` VALUES ('1', '雨果', '巴黎圣母院', '66', '2020-12-19 15:26:51', '巴黎圣母院是法国著名作家雨果的长篇小说。讲述的是丑聋人卡西莫多被巴黎圣母院的神父收养后作为撞钟人,神父内心丑恶,想要迫害吉ト赛女郎埃斯梅拉达。面目丑陋、心地善良的敲钟人卡西莫多为救女郎舍身的故事', '2022-08-21 13:37:14');
INSERT INTO `book_info` VALUES ('2', '列夫·托尔斯泰', '战争与和平', '98', '2020-12-19 15:28:36', '战争与和平是列夫·托尔斯泰写下的长篇小说。讲述的是俄、法两国再度交战时期,鲍尔康斯、别祖霍夫、罗斯托夫和库拉金四大贵族的经历为主线,在战争与和平的交替描写中把众多的事件和人物串联起来。战争和和平本来是反义词,单这本书却很好的描写了这两个词语背后的意义', '2022-08-21 13:37:17');
INSERT INTO `book_info` VALUES ('3', '高尔基', '童年', '56', '2022-08-21 14:35:02', '《童年》的作家是高尔基,这篇故事讲述的是小主人公阿廖沙在父亲去世之后,跟着母亲在外公家度过的岁月。他的外祖母十分爱他,为他讲了许多优美的童话,让他有了温暖的感觉,但他也目睹了舅舅为了争家产而打架,反应了一个家庭赤裸裸的生活故事', '2022-08-21 14:35:08');
INSERT INTO `book_info` VALUES ('4', '雨果', '悲惨世界', '48', '2022-08-21 14:35:05', '雨果以卓越的艺术魅力展示了资本主义社会奴役劳动人民、逼良为娼的残酷现实。雨果的这部传世之作,创造了一部反映法国现代社会生活和政治生活的长篇史话。', '2022-08-21 14:35:10');

-- mingqianbak
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for user_info:mingqianbak从库表
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(32) DEFAULT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '出生日期',
  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
  `updateTime` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES ('1', '雨果', '1924-03-10', '2022-08-21 13:36:20', '2022-08-21 13:36:27');
INSERT INTO `user_info` VALUES ('2', '列夫·托尔斯泰', '1330-01-10', '2022-08-21 13:36:23', '2022-08-21 13:36:30');
INSERT INTO `user_info` VALUES ('3', '余华', '1960-04-03', '2022-08-21 14:37:21', '2022-08-21 14:37:29');
INSERT INTO `user_info` VALUES ('4', '刘慈欣', '1963-06-06', '2022-08-21 14:37:26', '2022-08-21 14:37:32');

6-2:po

@Data
@TableName("book_info")
@ApiModel(value = "book_info实体")
public class BookInfoDO {

    private Integer id;

    private String author;

    private String name;

    private Long price;

    private Date createtime;

    private Date updatetime;

    private String description;

}
@Data
@TableName("user_info")
@ApiModel(value = "user_info实体")
public class UserInfoDO {

    private Integer id;

    private String name;

    private Date birthday;

    private Date createtime;

    private Date updatetime;

}

6-3:mapper(接口)

@Repository
public interface UserInfoMapper {

    List<UserInfoDO> selectAll();


}
@Repository
public interface BookInfoMapper {


    List<BookInfoDO> selectAll();


}

6-4:mapper(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.sunshine.mapper.primary.BookInfoMapper">
    <resultMap id="BaseResultMap" type="com.sunshine.pojo.domain.BookInfoDO">

        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="author" jdbcType="VARCHAR" property="author"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="price" jdbcType="DECIMAL" property="price"/>
        <result column="description" jdbcType="VARCHAR" property="description"/>
        <result column="createTime" jdbcType="TIMESTAMP" property="createtime"/>
        <result column="createTime" jdbcType="TIMESTAMP" property="updatetime"/>
    </resultMap>
    <select id="selectAll" resultMap="BaseResultMap">

        select id, author, name, price, createTime, description,updatetime
        from book_info
    </select>
</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="com.sunshine.mapper.datasource2.UserInfoMapper">
    <resultMap id="BaseResultMap" type="com.sunshine.pojo.domain.UserInfoDO">

        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="birthday" jdbcType="DATE" property="birthday"/>
        <result column="createTime" jdbcType="TIMESTAMP" property="createtime"/>
        <result column="createTime" jdbcType="TIMESTAMP" property="updatetime"/>
    </resultMap>
    <select id="selectAll" resultMap="BaseResultMap">

        select id, name, birthday ,createtime ,updatetime
        from user_info
    </select>
</mapper>

6-5:service

public interface BookInfoService {
    List<BookInfoDO> selectAll();
}

public interface UserInfoService {

    List<UserInfoDO> selectAll();
}

6-6:serviceImpl

@Service
public class BookInfoServiceImpl implements BookInfoService {

    @Autowired
    private BookInfoMapper bookInfoMapper;

    @Override
    public List<BookInfoDO> selectAll() {
        return bookInfoMapper.selectAll();
    }
}

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Override
    public List<UserInfoDO> selectAll() {
        return userInfoMapper.selectAll();
    }
}

6-7:controller

@RestController
@Api(tags = "用户-相关接口")
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;

    @ApiOperation(value = "列表查询")
    @ResponseBody
    @GetMapping(value = "/list")
    public Response selectAll() {
        List<UserInfoDO> userList = userInfoService.selectAll();
        return Response.success(userList);
    }
}
@RestController
@Api(tags = "书籍-相关接口")
@RequestMapping(value = "/books", produces = MediaType.APPLICATION_JSON_VALUE)
public class BookInfoController {

    @Autowired
    private BookInfoService bookInfoService;

    @ApiOperation(value = "列表查询")
    @GetMapping(value = "/list")
    public Response selectAll() throws Exception {
        List<BookInfoDO> books = bookInfoService.selectAll();
        return Response.success(books);
    }
}

6-8:postman测试在这里插入图片描述

在这里插入图片描述

七、注意

特别注意在配置配置文件的时候注意两点
1、数据库链接url:要写成jdbc-url:
2、在创建SqlSessionFactoryBean bean = new SqlSessionFactoryBean();针对mybatis;若是项目中使用了mybatis,则需要替换成:MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean(); 否则会报错:找不到baseMapper中的方法;
报错展示:
在这里插入图片描述

八、总结

以上方式单纯的使用JDBC的方式进行数据库链接,当实际项目开发过程中会使用池化思想,数据库连接池例如Druid
下篇研究Druid 连接池配置多数据源的情况。


版权声明:本文为TongHuYouthTeam原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。