zoukankan      html  css  js  c++  java
  • spring-boot整合mybatis和druid连接池(多数据源)

    spring-boot整合mybatis和druid连接池(多数据源)

    https://blog.csdn.net/liuxiao723846/article/details/80461071

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuxiao723846/article/details/80461071
    上一篇文章介绍了 spring-boot整合mybatis和druid连接池如何配置和使用,本篇文章是上篇的扩展,如果业务中出现了需要从多个数据源中获取数据,到底该如何实现?本文主要介绍在一种最为简单的实现方案:多数据源 - 多实例。 

    在上篇文章中不难看出Spring Boot中,通过为该数据源DataSource初始化一个与之对应的SessionFactory,从而实现连接。因此在面对多数据源的时候,可以分别为每个数据源写一个mybatis的config类,使其每个DataSource都拥有一个只属于自己的SessionFactory,这样就可以根据各自的mapper(dao)映射目录找到对应的mybaits实例。

    注:这种实现方法要求不同的mybatis实例的mapper映射目录(dao)不能相同。

    1、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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.edu.nuc</groupId>
    <artifactId>Test1</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>Test1</name>

    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>

    <mybatis-spring-boot>1.2.0</mybatis-spring-boot>
    <mysql-connector>5.1.39</mysql-connector>
    </properties>

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.5.RELEASE</version>
    </parent>

    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
    </dependency>

    <!-- spring boot -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    <exclusion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
    <!-- Spring Boot log4j依赖 -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.8.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
    </dependency>
    <!-- jsp -->
    <dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
    </dependency>
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    </dependency>

    <!-- Spring Boot Mybatis 依赖 -->
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis-spring-boot}</version>
    </dependency>
    <!-- Druid 数据连接池依赖 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.13</version>
    </dependency>
    <!-- MySQL 连接驱动依赖 -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>

    </dependencies>

    <build>
    <finalName>Test</finalName>
    <plugins>
    <!-- <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin> -->
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
    </plugin>
    </plugins>
    </build>
    </project>
    2、application.properties和数据源配置:

    1)application.properties配置:

    #---------------------ds1数据源(使用durid连接池)
    ds1.datasource.url=jdbc:mysql://ds1.w.abc.db:1883/ttengine?useUnicode=true&characterEncoding=utf8
    ds1.datasource.username=ds1
    ds1.datasource.password=ds1
    ds1.datasource.driverClassName=com.mysql.jdbc.Driver

    ds1.datasource.initialSize=20
    ds1.datasource.minIdle=20
    ds1.datasource.maxActive=200
    ds1.datasource.maxWait=60000
    ds1.datasource.timeBetweenEvictionRunsMillis=60000
    ds1.datasource.minEvictableIdleTimeMillis=300000
    ds1.datasource.testWhileIdle=true
    ds1.datasource.testOnBorrow=false
    ds1.datasource.testOnReturn=false
    ds1.datasource.poolPreparedStatements=true
    ds1.datasource.maxPoolPreparedStatementPerConnectionSize=20

    ds2.datasource.url=jdbc:mysql://ds2.w.abc.db:8907/toutiao?useUnicode=true&characterEncoding=utf8
    ds2.datasource.username=ds2
    ds2.datasource.password=^ds2
    ds2.datasource.driverClassName=com.mysql.jdbc.Driver
    #---------------------ds2数据源
    ds2.datasource.initialSize=20
    ds2.datasource.minIdle=20
    ds2.datasource.maxActive=200
    ds2.datasource.maxWait=60000
    ds2.datasource.timeBetweenEvictionRunsMillis=60000
    ds2.datasource.minEvictableIdleTimeMillis=300000
    ds2.datasource.testWhileIdle=true
    ds2.datasource.testOnBorrow=false
    ds2.datasource.testOnReturn=false
    ds2.datasource.poolPreparedStatements=true
    ds2.datasource.maxPoolPreparedStatementPerConnectionSize=20


    # 页面默认前缀目录
    spring.mvc.view.prefix=/WEB-INF/page/
    spring.mvc.view.suffix=.jsp
    由于我们使用druid连接池,所以我们需要定制DataSourceConfig(每个数据源都要定制一份)

    2)Datasource1Config:

    package nc.edu.nuc.Test.dao.mysql;

    import javax.sql.DataSource;

    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    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;

    import com.alibaba.druid.pool.DruidDataSource;

    @Configuration
    //扫描 Mapper 接口并容器管理
    @MapperScan(basePackages = Datasource1Config.PACKAGE, sqlSessionFactoryRef = "ds1SqlSessionFactory")
    public class Datasource1Config {
    // 精确到 master 目录,以便跟其他数据源隔离
    static final String PACKAGE = "nc.edu.nuc.Test.dao.mysql.ds1";
    static final String MAPPER_LOCATION = "classpath:mapper/ds1/*.xml";

    @Value("${ds1.datasource.url}")
    private String url;
    @Value("${ds1.datasource.username}")
    private String user;
    @Value("${ds1.datasource.password}")
    private String password;
    @Value("${ds1.datasource.driverClassName}")
    private String driverClass;

    @Value("${ds1.datasource.maxActive}")
    private Integer maxActive;
    @Value("${ds1.datasource.minIdle}")
    private Integer minIdle;
    @Value("${ds1.datasource.initialSize}")
    private Integer initialSize;
    @Value("${ds1.datasource.maxWait}")
    private Long maxWait;
    @Value("${ds1.datasource.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;
    @Value("${ds1.datasource.minEvictableIdleTimeMillis}")
    private Long minEvictableIdleTimeMillis;
    @Value("${ds1.datasource.testWhileIdle}")
    private Boolean testWhileIdle;
    @Value("${ds1.datasource.testWhileIdle}")
    private Boolean testOnBorrow;
    @Value("${ds1.datasource.testOnBorrow}")
    private Boolean testOnReturn;

    @Bean(name = "ds1DataSource")
    @Primary
    public DataSource ds1DataSource() {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName(driverClass);
    dataSource.setUrl(url);
    dataSource.setUsername(user);
    dataSource.setPassword(password);

    //连接池配置
    dataSource.setMaxActive(maxActive);
    dataSource.setMinIdle(minIdle);
    dataSource.setInitialSize(initialSize);
    dataSource.setMaxWait(maxWait);
    dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
    dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
    dataSource.setTestWhileIdle(testWhileIdle);
    dataSource.setTestOnBorrow(testOnBorrow);
    dataSource.setTestOnReturn(testOnReturn);
    dataSource.setValidationQuery("SELECT 'x'");

    dataSource.setPoolPreparedStatements(true);
    dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

    return dataSource;
    }

    @Bean(name = "ds1TransactionManager")
    @Primary
    public DataSourceTransactionManager ds1TransactionManager() {
    return new DataSourceTransactionManager(ds1DataSource());
    }

    @Bean(name = "ds1SqlSessionFactory")
    @Primary
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource ds1DataSource)
    throws Exception {
    final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(ds1DataSource);
    sessionFactory.setTypeAliasesPackage("nc.edu.nuc.Test.entity");
    sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
    .getResources(Datasource1Config.MAPPER_LOCATION));
    return sessionFactory.getObject();
    }
    }
    3)Datasource2Config:
    package nc.edu.nuc.Test.dao.mysql;

    import javax.sql.DataSource;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    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;

    import com.alibaba.druid.pool.DruidDataSource;

    @Configuration
    //扫描 Mapper 接口并容器管理
    @MapperScan(basePackages = Datasource2Config.PACKAGE, sqlSessionFactoryRef = "ds2SqlSessionFactory")
    public class Datasource2Config {
    // 精确到 master 目录,以便跟其他数据源隔离
    static final String PACKAGE = "nc.edu.nuc.Test.dao.mysql.ds2";
    static final String MAPPER_LOCATION = "classpath:mapper/ds2/*.xml";

    @Value("${ds2.datasource.url}")
    private String url;
    @Value("${ds2.datasource.username}")
    private String user;
    @Value("${ds2.datasource.password}")
    private String password;
    @Value("${ds2.datasource.driverClassName}")
    private String driverClass;

    @Value("${ds2.datasource.maxActive}")
    private Integer maxActive;
    @Value("${ds2.datasource.minIdle}")
    private Integer minIdle;
    @Value("${ds2.datasource.initialSize}")
    private Integer initialSize;
    @Value("${ds2.datasource.maxWait}")
    private Long maxWait;
    @Value("${ds2.datasource.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;
    @Value("${ds2.datasource.minEvictableIdleTimeMillis}")
    private Long minEvictableIdleTimeMillis;
    @Value("${ds2.datasource.testWhileIdle}")
    private Boolean testWhileIdle;
    @Value("${ds2.datasource.testWhileIdle}")
    private Boolean testOnBorrow;
    @Value("${ds2.datasource.testOnBorrow}")
    private Boolean testOnReturn;

    @Bean(name = "ds2DataSource")
    public DataSource ds2DataSource() {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName(driverClass);
    dataSource.setUrl(url);
    dataSource.setUsername(user);
    dataSource.setPassword(password);

    //连接池配置
    dataSource.setMaxActive(maxActive);
    dataSource.setMinIdle(minIdle);
    dataSource.setInitialSize(initialSize);
    dataSource.setMaxWait(maxWait);
    dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
    dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
    dataSource.setTestWhileIdle(testWhileIdle);
    dataSource.setTestOnBorrow(testOnBorrow);
    dataSource.setTestOnReturn(testOnReturn);
    dataSource.setValidationQuery("SELECT 'x'");

    dataSource.setPoolPreparedStatements(true);
    dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

    return dataSource;
    }

    @Bean(name = "ds2TransactionManager")
    public DataSourceTransactionManager ds2TransactionManager() {
    return new DataSourceTransactionManager(ds2DataSource());
    }

    @Bean(name = "ds2SqlSessionFactory")
    public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("ds2DataSource") DataSource ds2DataSource)
    throws Exception {
    final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(ds2DataSource);
    sessionFactory.setTypeAliasesPackage("nc.edu.nuc.Test.entity");
    sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
    .getResources(Datasource2Config.MAPPER_LOCATION));
    return sessionFactory.getObject();
    }
    }
    多数据源配置的时候注意,必须要有一个主数据源。

    @Primary 标志这个 Bean 如果在多个同类 Bean 候选时,该 Bean 优先被考虑。「多数据源配置的时候注意,必须要有一个主数据源,用 @Primary 标志该 Bean」
    @MapperScan 扫描 Mapper 接口并容器管理,包路径精确到 master,为了和下面 cluster 数据源做到精确区分
    @Value 获取全局配置文件 application.properties 的 kv 配置,并自动装配sqlSessionFactoryRef 表示定义了 key ,表示一个唯一 SqlSessionFactory 实例.

    4)说明:

    上面数据配置分别扫描nc.edu.nuc.Test.dao.mysql.ds1 和 nc.edu.nuc.Test.dao.mysql.ds2中定义的Mapper接口TestDao和DemoDao(可以在接口上配置@Mapper注解,也可以在springboot主类上统一加@MapperScan("..."))
    ds1对应 xml classpath:mapper/ds1下的sql文件,ds2对应 xml classpath:mapper/ds2下的sql文件,Mybatis 内部会使用反射机制运行去解析相应 SQL。
    3、其他:

    多数据源配置好后,接下来就和正常spring-boot的用法一样了。整个结构:

    1)crontroller:

    package nc.edu.nuc.Test.controller;

    import java.util.Date;
    import javax.servlet.http.HttpServletRequest;
    import nc.edu.nuc.Test.entity.Test;
    import nc.edu.nuc.Test.service.TestService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;

    @Controller
    public class TestController {
    private static final Logger logger = LoggerFactory.getLogger(TestController.class);

    @Autowired
    private TestService testService;

    @RequestMapping("/test")
    @ResponseBody
    public String test(HttpServletRequest request) {
    String name = request.getParameter("name");
    Test test = null;
    try {
    test = testService.findByName(name);
    } catch (Exception e) {
    test = new Test();
    logger.error("test error.",e);
    }
    logger.info("test....{}",name);
    return test.toString();
    }
    }
    2)service:

    package nc.edu.nuc.Test.service;

    import java.util.List;
    import nc.edu.nuc.Test.dao.mysql.ds1.TestDao;
    import nc.edu.nuc.Test.dao.mysql.ds2.DemoDao;
    import nc.edu.nuc.Test.entity.Demo;
    import nc.edu.nuc.Test.entity.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    @Service
    public class TestService{
    private static final Logger logger = LoggerFactory.getLogger(TestService.class);

    @Autowired
    private TestDao testDao;
    @Autowired
    private DemoDao demoDao;

    public Test findByName(String name) throws Exception{
    List<Demo> demoList = demoDao.getDemoList();
    logger.info(demoList.toString());
    return testDao.findByName(name);
    }
    }
    3)entity:

    package nc.edu.nuc.Test.entity;

    public class Demo {
    private Long id;
    private String title;
    private String descs;


    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    public String getTitle() {
    return title;
    }
    public void setTitle(String title) {
    this.title = title;
    }
    public String getDescs() {
    return descs;
    }
    public void setDescs(String descs) {
    this.descs = descs;
    }

    @Override
    public String toString() {
    return "Demo [id=" + id + ", title=" + title + ", descs=" + descs + "]";
    }
    }
    package nc.edu.nuc.Test.entity;

    public class Test {
    private Long id;
    private String name;
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public String toString() {
    return "Test [id=" + id + ", name=" + name + "]";
    }
    }
    4)dao:

    package nc.edu.nuc.Test.dao.mysql.ds1;

    import nc.edu.nuc.Test.entity.Test;
    import org.apache.ibatis.annotations.Param;

    public interface TestDao {
    Test findByName(@Param("name") String n);
    }
    package nc.edu.nuc.Test.dao.mysql.ds2;

    import java.util.List;
    import nc.edu.nuc.Test.entity.Demo;

    public interface DemoDao {
    List<Demo> getDemoList() throws Exception;
    }
    5)mapper sql文件:

    <?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="nc.edu.nuc.Test.dao.mysql.ds1.TestDao">
    <resultMap id="BaseResultMap" type="nc.edu.nuc.Test.entity.Test">
    <result column="id" property="id" />
    <result column="name" property="name" />
    </resultMap>

    <parameterMap id="Test" type="nc.edu.nuc.Test.entity.Test"/>

    <sql id="Base_Column_List">
    id,name
    </sql>
    <select id="findByName" resultMap="BaseResultMap" parameterType="java.lang.String">
    select
    <include refid="Base_Column_List" />
    from test
    where name = #{name}
    </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="nc.edu.nuc.Test.dao.mysql.ds2.DemoDao">
    <resultMap id="BaseResultMap" type="nc.edu.nuc.Test.entity.Demo">
    <result column="id" property="id" />
    <result column="title" property="title" />
    <result column="descs" property="descs" />
    </resultMap>

    <parameterMap id="Demo" type="nc.edu.nuc.Test.entity.Demo"/>

    <sql id="Base_Column_List">
    id,title,descs
    </sql>

    <select id="getDemoList" resultType="Demo">
    select
    <include refid="Base_Column_List" />
    from demo
    </select>

    </mapper>

    6)app启动类:

    package nc.edu.nuc.Test;

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

    /**
    * Hello world!
    * 可以统一用@MapperScan指定扫描的dao,也可以在每个dao上添加@Mapper
    */
    @SpringBootApplication
    //mapper 接口类扫描包配置
    @MapperScan("nc.edu.nuc.Test.dao.mysql")
    public class App {
    public static void main( String[] args ) {
    SpringApplication.run(App.class, args);
    }
    }
    参考:https://github.com/YHYR/Mybatis

    https://github.com/JeffLi1993/springboot-learning-example/blob/master/springboot-mybatis-mutil-datasource/src/main/java/org/spring/springboot/service/impl/UserServiceImpl.java

    https://www.bysocket.com/?p=1712

    https://blog.csdn.net/YHYR_YCY/article/details/78894940
    ---------------------
    作者:赶路人儿
    来源:CSDN
    原文:https://blog.csdn.net/liuxiao723846/article/details/80461071
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    计算机世界中解决问题的三种技术手段
    应用程序池的经典模式与集成模式的区别
    sh文件的编译
    flex学习开始了
    com,ActiveX,Ole之间的关系学习总结
    "正在等待localhost。。”问题的解决
    一些感悟
    面向对象软件工程方法学实践【转】
    外连接在sqlserver和access之间的差异
    外连接在sqlserver和access之间的差异
  • 原文地址:https://www.cnblogs.com/handsome1013/p/11121982.html
Copyright © 2011-2022 走看看