10、SpringBoot-mybatis-plus-druid多源数据

系列导航

springBoot项目打jar包

1、springboot工程新建(单模块)

2、springboot创建多模块工程

3、springboot连接数据库

4、SpringBoot连接数据库引入druid

5、SpringBoot连接数据库引入mybatis

6、SpringBoot-mybatis分页实现pagehelper

7、SpringBoot-mybatis-plus引入

8、SpringBoot 事务

9、SpringBoot-mybatis-druid多源数据多源数据

10、SpringBoot-mybatis-plus-druid多源数据

11、SpringBoot-mybatis-plus-druid多源数据事务

12、SpringBoot-mybatis-plus-ehcache

13、SpringBoot-配置文件里密码加密

14、SpringBoot-easyexcel导出excle

完结

     本文介绍如何在mybatis-plus上使用多源数据,本来以为mybatis-plus上多源数据和mybatis差不多实际操作后发现真还是不太一样。mybatis-plus的配置多源数据的大致思路就是,利用了切面的思想,访问那个mapper就把当前数据连接切换到对应的数据源上。

1数据库中创建表

zy数据库:

CREATE TABLE TEST_BLOCK_T   
(
  BLOCK_ID         VARCHAR2(10 BYTE) PRIMARY   KEY,    --编码
  BLOCK_NAME       VARCHAR2(200 BYTE)                    --资源名称 
); 
 Insert into TEST_BLOCK_T (BLOCK_ID, BLOCK_NAME) Values ('1', 'java');
COMMIT;

yc数据库:

CREATE TABLE TEST_USER_T   
(
  USER_ID         VARCHAR2(10 BYTE) PRIMARY   KEY,     
  NAME            VARCHAR2(200 BYTE)                      
);
Insert into TEST_USER_T (USER_ID, NAME) Values ('1', '张三');
COMMIT;

2、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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.1.17.RELEASE</spring-boot.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- oracle驱动 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>

        <!-- 集成druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

 

        <!--集成mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>2.1.9</version>
        </dependency>


        <!-- aop切面 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>


        <!-- 省略get/set等方法 日志打印 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>


    </dependencies>



</project>

3、      application.properties配置

# 应用名称
spring.application.name=demo
# 应用服务 WEB 访问端口
server.port=8080


spring.aop.proxy-target-class=true
spring.aop.auto=true

spring.datasource.druid.db1.url=jdbc:oracle:thin:@192.168.1.100:1521:orcl
spring.datasource.druid.db1.username=zy
spring.datasource.druid.db1.password=123
spring.datasource.druid.db1.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.druid.db1.initialSize=5
spring.datasource.druid.db1.minIdle=5
spring.datasource.druid.db1.maxActive=20

spring.datasource.druid.db2.url=jdbc:oracle:thin:@192.168.1.100:1521:orcl
spring.datasource.druid.db2.username=yc
spring.datasource.druid.db2.password=123
spring.datasource.druid.db2.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.druid.db2.initialSize=5
spring.datasource.druid.db2.minIdle=5
spring.datasource.druid.db2.maxActive=20

#开启sql打印
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

4、文件目录

 

 

主要源码:

MybatisPlusConfig.java

DataSourceSwitchAspect.java

 

5、源码

package com.example.demo.config;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Component
@Order(value = -100)
@Slf4j
@Aspect
public class DataSourceSwitchAspect {

    @Pointcut("execution(* com.example.demo.mapper.db1..*.*(..))")
    private void db1Aspect() {
    }

    @Pointcut("execution(* com.example.demo.mapper.db2..*.*(..))")
    private void db2Aspect() {
    }


    @Before("db1Aspect()")
    public void db1() {
        log.info("切换到db1 数据源...");
        DbContextHolder.setDbType(DBTypeEnum.db1);
    }

    @Before("db2Aspect()")
    public void db2() {
        log.info("切换到db2 数据源...");
        DbContextHolder.setDbType(DBTypeEnum.db2);
    }

}

 

package com.example.demo.config;



public class DbContextHolder {

    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    /**
     * 设置数据源
     * @param dbTypeEnum
     */
    public static void setDbType(DBTypeEnum dbTypeEnum) {
        contextHolder.set(dbTypeEnum.getValue());
    }

    /**
     * 取得当前数据源
     * @return
     */
    public static String getDbType() {
        return (String) contextHolder.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

 

package com.example.demo.config;


public enum DBTypeEnum {

    db1("db1"), db2("db2") ;
    private String value;

    DBTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

 

package com.example.demo.config;


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return  DbContextHolder.getDbType();
    }
}

 

package com.example.demo.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setLocalPage(true);
        return paginationInterceptor;
    }

    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db1")
    public DataSource db1() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db2")
    public DataSource db2() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 动态数据源配置
     *
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("db1") DataSource db1,
                                         @Qualifier("db2") DataSource db2) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.db1.getValue(), db1);
        targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(db2);
        return dynamicDataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2()));

        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        //添加分页功能
        sqlSessionFactory.setPlugins(new Interceptor[]{
                paginationInterceptor()
        });
        return sqlSessionFactory.getObject();
    }


}

 

package com.example.demo.controller;


import com.example.demo.service.ManySourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/hello")
public class ManySourceController {

    @Autowired
    ManySourceService manySourceService;

    @GetMapping("/getZyBlock")
    @ResponseBody
    public String test1() {
        return  manySourceService.getZyBlock();

    }

    @GetMapping("/getYcUser")
    @ResponseBody
    public String test2() {
        return manySourceService.getYcUser();

    }


    @PostMapping("/insertZyBlock")
    @ResponseBody
    public String test3() {
        return  manySourceService.insertZyBlock();

    }

    @PostMapping("/insertYcUser")
    @ResponseBody
    public String test4() {
        return manySourceService.insertYcUser();

    }

    @PostMapping("/insertMany")
    @ResponseBody
    public String test5() {
        return manySourceService.insertMany();

    }


}

 

package com.example.demo.domain.db1;


import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;


@TableName(value = "TEST_BLOCK_T")
public class Block {
    private static final long serialVersionUID = 1L;

    @TableId
    private String blockId;
    /**
     * $field.comment。
     */
    private String blockName;

    public String getBlockId() {
        return blockId;
    }

    public void setBlockId(String blockId) {
        this.blockId = blockId;
    }

    public String getBlockName() {
        return blockName;
    }

    public void setBlockName(String blockName) {
        this.blockName = blockName;
    }

    @Override
    public String toString() {
        return "TEST_BLOCK_T{" +
                "blockId='" + blockId + '\'' +
                ", blockName='" + blockName + '\'' +
                '}';
    }
}

 

package com.example.demo.domain.db2;


import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;



@TableName(value = "TEST_USER_T")
public class User {
    private static final long serialVersionUID = 1L;

    @TableId
    private String userId;
    /**
     * $field.comment。
     */
    private String name;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId='" + userId + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

 

package com.example.demo.mapper.db1;


import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.example.demo.domain.db1.Block;

public interface BlockMapper extends BaseMapper<Block> {

}

 

package com.example.demo.mapper.db2;


import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.example.demo.domain.db2.User;


public interface UserMapper extends BaseMapper<User> {

}

 

package com.example.demo.service;



import com.example.demo.domain.db1.Block;
import com.example.demo.domain.db2.User;
import com.example.demo.mapper.db1.BlockMapper;
import com.example.demo.mapper.db2.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ManySourceService {




    @Autowired
    BlockMapper blockMapper;

    @Autowired
    UserMapper userMapper;

    //获取zy库中的block中的数据
    public String getZyBlock() {
        return  blockMapper.selectById("99999").toString();

    }

    //获取yc库中的user中的数据
    public String getYcUser() {
        return  userMapper.selectById("2").toString() ;
    }

    public String insertZyBlock() {
        Block block = new Block();
        block.setBlockId("99999");
        block.setBlockName("PHP");
        return  blockMapper.insert(block)+"";
    }

    public String insertYcUser() {
        User user = new User();
        user.setUserId("2");
        user.setName("李四");
        return  userMapper.insert(user)+"";
    }

    //@Transactional  加了事务会报错
    public String insertMany() {
        Block block = new Block();
        block.setBlockId("99999");
        block.setBlockName("PHP");
        blockMapper.insert(block) ;

        User user = new User();
        user.setUserId("2");
        user.setName("李四");
        userMapper.insert(user) ;
        return "1";
    }

}

 

package com.example.demo;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.example.demo.mapper.db*")
public class DemoApplication {

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

}

6、启动项目访问项目

清空yc库里的表TEST_USER_T 和 zy库里的表TEST_BLOCK_T

(1)访问http://localhost:8080/hello/insertZyBlock 成功插入数据到TEST_BLOCK_T

(2)访问http://localhost:8080/hello/insertYcUser成功插入数据到TEST_USER_T

说明分别向不同数据源的数据库的插入没有问题。

(3)访问http://localhost:8080/hello/getZyBlock

 

 

 

(4)访问http://localhost:8080/hello/getYcUser

 

 

 

 

说明分别从不同数据源的数据库的查询没有问题。

 

再次清空yc库里的表TEST_USER_T 和 zy库里的表TEST_BLOCK_T

(5)访问http://localhost:8080/hello/insertMany

一个方法中向TEST_USER_T 和TEST_BLOCK_T插入数据插入成功数据库里的数据生成了。

 

日志中看到同一个方法中向不同的数据库中插入数据程序会自动的切换数据源。

 

注:下面就不能加事务Transactional了,这里估计是我没有用对,如果有能解决的道友可以反馈一下。

//@Transactional 加了事务会报错
public String insertMany() 

posted @ 2022-04-20 12:41  万笑佛  阅读(224)  评论(0编辑  收藏  举报