SpringBoot 集成多数据源

一个项目中怎么划分数据库,可以通过具体业务需求。

项目中数据源怎么如何划分,通过注解的方式@Datasource(ref="") 在方法上指定,会连接指定的数据源,这种方式比较繁琐。如果有1000个方法,就得写1000个这种注解。所以一般通过分包名的方式。

通过分包名来划分数据源:

1,mysql 里面有两个库,testdb,testdb2,里面各有一张user表,数据结构是一样的

2,建立实体类:user

@Data //相当于@Setter @Getter
public class User {
    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
}

2,datasource 包下有DataSource1Config,DataSource2Config,如下:

package com.baiyue.datasource;

import javax.sql.DataSource;

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 org.springframework.jdbc.datasource.DataSourceTransactionManager;

// DataSource01
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "com.baiyue.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSource1Config {
    @Bean(name = "db1DataSource") //@Bean是注入到Spring 容器中
    @ConfigurationProperties(prefix = "spring.datasource.db1")//读取配置文件中以spring.datasource.db1 开头的
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Primary
    @Bean(name = "db1SqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:com/baiyue/db1/mapping/*Mapper.xml"));
        return bean.getObject();
    }

    /**
     * 事务
     */
    @Bean(name = "db1TransactionManager")
    public DataSourceTransactionManager testTransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "db1SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

DataSource2:

package com.baiyue.datasource;

import javax.sql.DataSource;

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 org.springframework.jdbc.datasource.DataSourceTransactionManager;

// DataSource01
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "com.baiyue.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DataSource2Config {
    
    @Bean(name = "db2DataSource") //@Bean是注入到Spring 容器中
    @ConfigurationProperties(prefix = "spring.datasource.db2")//读取配置文件中以spring.datasource.db2 开头的
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }
    

    @Bean(name = "db2SqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:com/baiyue/db2/mapping/*Mapper.xml"));
        return bean.getObject();
    }

    /**
     * 事务
     */
    @Bean(name = "db2TransactionManager")
    public DataSourceTransactionManager testTransactionManager(@Qualifier("db2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "db2SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

通过 @Configuration // 注册到springboot容器中,在启动类中会去读取所有的Bean,通过两个类以及配置文件,能够获取到不同包下的业务层对应不同的数据源..

#多数据源
spring:
  datasource:
    db1:
      driver-class-name: com.mysql.jdbc.Driver
      jdbcUrl: jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8
      username: root
      password: 123456

    db2:
      driver-class-name: com.mysql.jdbc.Driver
      jdbcUrl: jdbc:mysql://localhost:3306/testdb2?useUnicode=true&characterEncoding=utf-8
      username: root
      password: 123456

3,db1 下的mapper,xml,service,sevice层需要指定业务相应的事务管理,否则会报有两个事务管理的错

package com.baiyue.db1.mapper;

import com.baiyue.entity.User;

public interface UserMapperdb1 {

    void insertUser(User user);

    User selectUserById(int id);

}
<?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.baiyue.db1.mapper.UserMapperdb1">

    <!-- 根据 id 查询 user 表中的数据 id:唯一标识符,此文件中的id值不能重复 resultType:返回值类型,一条数据库记录也就对应实体类的一个对象 
        parameterType:参数类型,也就是查询条件的类型 -->
    <select id="selectUserById" resultType="com.baiyue.entity.User" parameterType="int">
        <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->
        select * from user where id = #{id}
    </select>

    <insert id="insertUser" parameterType="com.baiyue.entity.User">
        insert into
        user(id,username,sex,birthday,address)
        value(#{id},#{username},#{sex},#{birthday},#{address})
    </insert>

</mapper>
package com.baiyue.db1.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baiyue.db1.mapper.UserMapperdb1;
import com.baiyue.entity.User;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class UserServicedb1 {

@Override
public String toString() {
    // TODO Auto-generated method stub
    return super.toString();
}
    
    @Autowired
    private UserMapperdb1 userMapper;
    
    @Transactional("db1TransactionManager")//指定事务管理
    public void insertUser(User user) {
        userMapper.insertUser(user);
    };

    public User selectUserById(int id) {
        User user = userMapper.selectUserById(id);
        return user;
    };

}

4,同理,db2 的mapper,xml,service

package com.baiyue.db2.mapper;

import com.baiyue.entity.User;

public interface UserMapperdb2 {

    void insertUser(User user);

    User selectUserById(int id);
}
<?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.baiyue.db2.mapper.UserMapperdb2">

    <!-- 根据 id 查询 user 表中的数据 id:唯一标识符,此文件中的id值不能重复 resultType:返回值类型,一条数据库记录也就对应实体类的一个对象 
        parameterType:参数类型,也就是查询条件的类型 -->
    <select id="selectUserById" resultType="com.baiyue.entity.User" parameterType="int">
        <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->
        select * from user where id = #{id}
    </select>

    <insert id="insertUser" parameterType="com.baiyue.entity.User">
        insert into
        user(id,username,sex,birthday,address)
        value(#{id},#{username},#{sex},#{birthday},#{address})
    </insert>
</mapper>
package com.baiyue.db2.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baiyue.db2.mapper.UserMapperdb2;
import com.baiyue.entity.User;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class UserServicedb2 {

    @Autowired
    private UserMapperdb2 userMapper;

    @Transactional("db2TransactionManager")//指定事务管理
    public void insertUser(User user) {
        log.info("正在添加");
        userMapper.insertUser(user);
    };

    public User selectUserById(int id) {
        User user = userMapper.selectUserById(id);
        return user;
    };

}

5,controller 层:

package com.baiyue.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baiyue.db1.service.UserServicedb1;
import com.baiyue.db2.service.UserServicedb2;
import com.baiyue.entity.User;

@RestController
public class Mybatis {
    
    @Autowired
    private UserServicedb1 userService1;
    
    @Autowired
    private UserServicedb2 userService2;
    
    @RequestMapping("/insertUserdb1")
    public String insertUserdb1(){
        User user = new User();
        user.setUsername("chris");
        user.setSex("male");
        userService1.insertUser(user);
        return "db1success";
    }
    
    @RequestMapping("/insertUserdb2")
    public String insertUserdb2() {
        User user = new User();
        user.setUsername("chris");
        user.setSex("male");
        userService2.insertUser(user);
        return "db2success";
    }

}

6,启动类

@MapperScan({"com.baiyue.db1.mapper","com.baiyue.db2.mapper"})
@ComponentScan(basePackages = "com.baiyue") //因为有一些bean 不在当前包或者子包下面,所以@SpringBootApplication 会有些bean 扫不到
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

 

这样,能够多数据源操作了。。。

 

posted @ 2019-07-16 14:34  Chris,Cai  阅读(326)  评论(0编辑  收藏  举报