单数据源的下Spring Boot的配置非常简单,只需要在 application.properties 文件中配置数据库的相关连接参数即可。但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源。

一 开发前的准备

1.1 环境参数

  • 开发工具:IDEA
  • 基础工具:Maven+JDK17
  • 所用技术:SpringBoot+Mybatis
  • 数据库:MySQL8
  • SpringBoot版本:3.0.2

1.2 创建工程

创建一个基本的 SpringBoot 项目

1.3 创建两个数据库和 user 用户表、money工资详情表


CREATE TABLE `money` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `basic` int DEFAULT NULL COMMENT '基本工资',
  `reward` int DEFAULT NULL COMMENT '奖金',
  `punishment` int DEFAULT NULL COMMENT '惩罚金',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(33) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `money` double DEFAULT NULL COMMENT '账户余额',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

1.4 配置 pom 文件中的相关依赖

<dependencies>
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
             <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

1.5 配置 application.properties

注意事项:

在1.0 配置数据源的过程中主要是写成:spring.datasource.url 和spring.datasource.driverClassName。 而在2.0升级之后需要变更成:spring.datasource.jdbc-url和spring.datasource.driver-class-name!不然在连接数据库时可能会报下面的错误:

### Error querying database.  Cause: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
# 配置第一个数据源
spring.datasource.hikari.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/erp?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.hikari.db1.username=root
spring.datasource.hikari.db1.password=0000
spring.datasource.hikari.db1.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置第二个数据源
spring.datasource.hikari.db2.jdbc-url=jdbc:mysql://127.0.0.1:3306/erp1?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.hikari.db2.username=root
spring.datasource.hikari.db2.password=0000
spring.datasource.hikari.db2.driver-class-name=com.mysql.cj.jdbc.Driver

1.6 创建用户类 Bean和工资详情类 Bean

User.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class User {
    private int id;
    private String name;
    private int age;
    private double money;

}

Money.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Money {
    private int id;
    //基本工资
    private int basic;
    //奖金
    private int reward;
    //罚款
    private int punishment;

}

二 数据源配置

通过 Java 类来实现对两个数据源的配置,这一部分是最关键的部分了,这里主要提一下下面这几点:

  • @MapperScan 注解中我们声明了使用数据库1的dao类所在的位置,还声明了 SqlSessionTemplate 。SqlSessionTemplate是MyBatis-Spring的核心。这个类负责管理MyBatis的SqlSession,调用MyBatis的SQL方法,翻译异常。SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用。
  • 由于我使用的是全注解的方式开发,所以下面这条找并且解析 mapper.xml 配置语句被我注释掉了 bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/db2/*.xml"));
  • 比如我们要声明使用数据1,直接在 dao 层的类上加上这样一个注释即可:@Qualifier("db1SqlSessionTemplate")
  • 我们在数据库1配置类的每个方法前加上了 @Primary 注解来声明这个数据库时默认数据库,不然可能会报错。

DataSource1Config.java

@Configuration
@MapperScan(basePackages = "com.example.datasource.dao", sqlSessionTemplateRef = "db1SqlSessionTemplate")
public class DataSource1Config {

    /**
     * 生成数据源.  @Primary 注解声明为默认数据源
     */

    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.db1")
    @Primary
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 创建 SqlSessionFactory
     */
    @Bean(name = "db1SqlSessionFactory")
    @Primary
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 手动设置日志实现
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        sqlSessionFactoryBean.setConfiguration(config);
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 配置事务管理
     */

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


    /**
     * 配置SqlSessionTemplate
     */
    @Bean(name = "db1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

DataSource2Config.java

@Configuration
@MapperScan(basePackages = "com.example.datasource.dao2", sqlSessionTemplateRef = "db2SqlSessionTemplate")
public class DataSource2Config {

    /**
     * 生成数据源
     * 配置SqlSessionFactory
     * 配置SqlSessionTemplate
     */

    @Bean(name = "db2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.db2")
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * SqlSessionTemplate是MyBatis-Spring的核心。这个类负责管理MyBatis的SqlSession,调用MyBatis的SQL方法,翻译异常。
     * SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用。
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "db2SqlSessionTemplate")
    public SqlSessionTemplate db2SqlSessionTemplate(
            @Qualifier("db2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);


        // 手动设置日志实现
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        sqlSessionFactoryBean.setConfiguration(config);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver()
                        .getResources("classpath*:mapper/*.xml")
        );
        sqlSessionFactoryBean.setTypeAliasesPackage("com.example.datasource.pojo");
        return new SqlSessionTemplate(sqlSessionFactoryBean.getObject());

    }
    @Bean(name = "db2TransactionManager")
    public DataSourceTransactionManager db1TransactionManager(@Qualifier("db2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }


}

三 Dao 层开发和 Service 层开发

新建两个不同的包存放两个不同数据库的 dao 和 service。

3.1 Dao 层

对于两个数据库,我们只是简单的测试一个查询这个操作。

UserDao.java

@Qualifier("db1SqlSessionTemplate")
public interface UserDao {

    /**
     * 通过名字查询用户信息
     */
    @Select("select * from user where name=#{name}")
    User findUserByName(String name);
}

MoneyDao.java

@Qualifier("db2SqlSessionTemplate")
public interface MoneyDao {


    /**
     * 通过id 查看工资详情
     */
    @Select("SELECT * FROM money WHERE id = #{id}")
    Money findMoneyById(@Param("id") int id);
}

3.2 Service 层

UserService.java

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    /**
     * 根据名字查找用户
     */
    public User selectUserByName(String name) {
        return userDao.findUserByName(name);
    }
}

MoneyService.java

@Service
public class MoneyService {


    @Autowired
    private MoneyDao moneyDao;


    /**
     * 根据id查看money信息
     *
     * @param id money的id属性
     */
    public Money selectMoney(int id) {
        return moneyDao.findMoneyById(id);
    }
}

四 Controller层

UserController.java

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/query")
    public User testQuery() {
        return userService.selectUserByName("jq");
    }
}

MoneyController.java

@RestController
@RequestMapping("/money")
public class MoneyController {

    @Autowired
    private MoneyService moneyService;

    @GetMapping("/selectMoney")
    public Money selectMoney(@RequestParam(value = "idd") int id) {
       return moneyService.selectMoney(id);
    }

}

五 启动类

//此注解表示SpringBoot启动类
@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

}

分类: SpringBoot

0 条评论

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注