spring boot多数据源整合mybatis通用mapper

本文将介绍spring boot下如何配置多数据源,持久层框架使用mybatis。附源码(开发工具idea,数据库连接池使用druid,项目管理工具maven)

目录

1、首先搭建项目double_db

2、再按照以下结构配置项目目录结构

3、配置application.properties

4、整合mybatis的通用mapper

4.1配置数据库连接池druid

4.2 配置mybatis的分页插件PageHelper

4.3 新建通用的基础mapper来继承mybatis的通用mapper

5、配置mvc

6、配置多数据源

6.1 配置主数据源

6.2 配置副数据源

7、创建不同数据源的实体类

7.1创建数据库

7.2新建对应的实体类

8、编写不同数据源的mapper

10、编写service

11、编写controller

12、启动项目

13、项目源码下载路径

手编不易,转载或参考请注明链接,谢谢!


1、首先搭建项目double_db

下面是pom文件



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.1.RELEASE
         
    
    com.harris
    double_db
    0.0.1-SNAPSHOT
    double_db
    Demo project for Spring Boot

    
        UTF-8
        UTF-8
        1.8
    

    
        
        
            com.alibaba
            druid-spring-boot-starter
            1.1.6
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        
        
            tk.mybatis
            mapper-spring-boot-starter
            1.2.4
        
        
            mysql
            mysql-connector-java
            8.0.12
        
        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            1.1.1
        

        
            org.springframework.boot
            spring-boot-starter-undertow
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-devtools
            true
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


2、再按照以下结构配置项目目录结构:

(后续将讲解每个目录的用途)

spring boot多数据源整合mybatis通用mapper_第1张图片

3、配置application.properties:

(为模拟多数据源,本项目连接本地两个不同数据库进行演示)

logging.level.com.harris.double_db.mapper = debug

spring.datasource1.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource1.url = jdbc:mysql://localhost:3306/one?serverTimezone=UTC&userUnicode=true&characterEncoding=utf-8&&useSSL=false
spring.datasource1.username = root
spring.datasource1.password = 123456
##Druid
# 初始化大小,最小,最大
spring.datasource1.druid.initial-size=10
spring.datasource1.druid.max-active=500
spring.datasource1.druid.min-idle=5
# 配置获取连接等待超时的时间
spring.datasource1.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource1.druid.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource1.druid.min-evictable-idle-time-millis=300000
spring.datasource1.druid.validation-query=SELECT 'X' FROM DUAL
spring.datasource1.druid.test-while-idle=true
spring.datasource1.druid.test-on-borrow=false
spring.datasource1.druid.test-on-return=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource1.druid.pool-prepared-statements=true
spring.datasource1.druid.max-pool-prepared-statement-per-connection-size=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource1.druid.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource1.druid.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000


spring.datasource2.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource2.url = jdbc:mysql://localhost:3306/two?serverTimezone=UTC&userUnicode=true&characterEncoding=utf-8&&useSSL=false
spring.datasource2.username = root
spring.datasource2.password = 123456
##Druid
# 初始化大小,最小,最大
spring.datasource2.druid.initial-size=10
spring.datasource2.druid.max-active=500
spring.datasource2.druid.min-idle=5
# 配置获取连接等待超时的时间
spring.datasource2.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource2.druid.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource2.druid.min-evictable-idle-time-millis=300000
spring.datasource2.druid.validation-query=SELECT 'X' FROM DUAL
spring.datasource2.druid.test-while-idle=true
spring.datasource2.druid.test-on-borrow=false
spring.datasource2.druid.test-on-return=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource2.druid.pool-prepared-statements=true
spring.datasource2.druid.max-pool-prepared-statement-per-connection-size=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource2.druid.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource2.druid.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

4、整合mybatis的通用mapper

4.1配置数据库连接池druid

新建DruidConfig.java

package com.harris.double_db.config;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;

/**
 * @author HCJ
 */
@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DruidConfig {

    /**
     * 注册一个StatViewServlet
     * @return
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
         ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
         //添加初始化参数
         servletRegistrationBean.setServlet(new StatViewServlet());
         servletRegistrationBean.setUrlMappings(Arrays.asList("/druid/*"));
         //白名单:
         servletRegistrationBean.addInitParameter("allow","");
         //IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
         servletRegistrationBean.addInitParameter("deny","");
         //登录查看信息的账号密码.
         servletRegistrationBean.addInitParameter("loginUsername","admin");
         servletRegistrationBean.addInitParameter("loginPassword","admin");
         //是否能够重置数据.
         servletRegistrationBean.addInitParameter("resetEnable","true");

         return servletRegistrationBean;
    }

    /**
     * 注册一个:filterRegistrationBean
     * @return
     */
    @Bean
    public FilterRegistrationBean druidStatFilter2(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        //添加过滤规则.
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        //添加不需要忽略的格式信息.
        filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");

        return filterRegistrationBean;
    }

}

4.2 配置mybatis的分页插件PageHelper

新建MybatisConfig.java

package com.harris.double_db.config;

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * 注册MyBatis分页插件PageHelper
 * @author HCJ
 */
@Configuration
public class MybatisConfig {
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

4.3 新建通用的基础mapper来继承mybatis的通用mapper

新建接口BaseMapper.java

package com.harris.double_db.base;

import tk.mybatis.mapper.common.ConditionMapper;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
import tk.mybatis.mapper.common.RowBoundsMapper;

/**
 * @author HCJ
 */
public interface BaseMapper extends Mapper,MySqlMapper,ConditionMapper,RowBoundsMapper {
}

后续项目的实体类只需要继承该BaseMapper即可使用通用mapper

5、配置mvc

新建WebMvcConfig.java

package com.harris.double_db.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.Date;

import static io.undertow.util.DateUtils.parseDate;


/**
 * @author HCJ
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{

    private final Logger logger = LoggerFactory.getLogger(WebMvcConfig.class);
    static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }

    @Bean
    public Converter dateConverter(){
        return new Converter() {
            @Override
            public Date convert(String s) {
                return parseDate(s);
            }
        };
    }

    //解决跨域问题
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                .maxAge(3600);
    }

}

6.配置多数据源

在步骤三中我以配置了两个数据源,由于使用了多个数据源,所以无法单通过配置文件告诉程序哪个mapper要使用哪个数据源因此还需要通过配置类说明。

6.1 配置主数据源

在config下新建一个包dataSource用于反正多数据原的配置类

新建DataSourceOneConfig.java

package com.harris.double_db.config.dataSource;

/**
 * @Author: he changjie on 2019/1/3
 * @Description:
 */

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.harris.double_db.mapper.source1", sqlSessionTemplateRef = "sqlSessionTemplateOne")
public class DataSourceOneConfig {

    @Bean(name = "dataSourceOne")
    @ConfigurationProperties(prefix = "spring.datasource1")
    @Primary //设置主数据源
    public DataSource DataSourceOne(){
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;

    }

    @Bean(name = "sqlSessionFactoryOne")
    @Primary
    public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceOne") DataSource dataSource)throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

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

    @Bean(name = "sqlSessionTemplateOne")
    @Primary
    public SqlSessionTemplate sqlSessionTemplateOne(@Qualifier("sqlSessionFactoryOne") SqlSessionFactory sqlSessionFactory)throws Exception{
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

注:

  1. 因为使用了多数据源,将无法从配置文件中配置mapper扫描路径,因此需要使用@MapperScan注解来扫描该数据源下的mapper
  2. @Bean声明实例的名称,防止多数据源注入冲突
  3. @Primary声明为主数据源,在多数据源下建议声明一个数据源为主数据源
  4. @ConfigurationProperties(prefix = "spring.datasource1")注解声明该bean对应配置文件在前缀为spring.datasource1的配置属性

6.2 配置副数据源

新建DataSourceTwoConfig.java

内容与主数据源配置类基本相同,因此不再说明

package com.harris.double_db.config.dataSource;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;

/**
 * @author HCJ
 */
@Configuration
@MapperScan(basePackages = "com.harris.double_db.mapper.source2", sqlSessionTemplateRef = "sqlSessionTemplateTwo")
public class DataSourceTwoConfig {

    @Bean(name = "dataSourceTwo")
    @ConfigurationProperties(prefix = "spring.datasource2")
    public DataSource DataSourceTwo() {
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;
    }

    @Bean(name = "sqlSessionFactoryTwo")
    public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceTwo") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean(name = "dataSourceTransactionManagerTwo")
    public DataSourceTransactionManager dataSourceTransactionManagerOne(@Qualifier("dataSourceTwo") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "sqlSessionTemplateTwo")
    public SqlSessionTemplate sqlSessionTemplateOne(@Qualifier("sqlSessionFactoryTwo") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

至此多数据源的配置已基本完工,其余内容和普通spring boot的项目基本相当。

7、创建不同数据源的实体类

7.1创建数据库

在本地新建数据库one,添加表my_user_one,表为演示表,字段简单演示,各位可根据实际项目调整。

spring boot多数据源整合mybatis通用mapper_第2张图片

在本地新建数据库two,添加表my_user_two

spring boot多数据源整合mybatis通用mapper_第3张图片

7.2新建对应的实体类

one、two分别对应两个数据源下数据库的表

新建MyUserOne.java

package com.harris.double_db.entity;

import javax.persistence.Table;

/**
 * @author HCJ
 */
@Table(name = "my_user_one")
public class MyUserOne {

  private String name;
  private String age;

  public String getName() {
    return name;
  }

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

  public String getAge() {
    return age;
  }

  public void setAge(String age) {
    this.age = age;
  }
}

新建MyUserTwo.java

package com.harris.double_db.entity;

import javax.persistence.Table;

/**
 * @author HCJ
 */
@Table(name = "my_user_two")
public class MyUserTwo {
  private String name;
  private String age;

  public String getName() {
    return name;
  }

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

  public String getAge() {
    return age;
  }

  public void setAge(String age) {
    this.age = age;
  }

}

8、编写不同数据源的mapper

在mapper包下新建source1和source2两个包,用于编写不同数据源下的mapper

在mapper.source1下新建接口MyOneMapper.java

package com.harris.double_db.mapper.source1;

import com.harris.double_db.base.BaseMapper;
import com.harris.double_db.entity.MyUserOne;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Author: he changjie on 2019/1/3
 * @Description:
 */
@Repository
public interface MyOneMapper extends BaseMapper {
    /**
     * 1
     * @return
     */
    List queryAll1();
}

在mapper.source2下新建接口MyTwoMapper.java

package com.harris.double_db.mapper.source2;

import com.harris.double_db.base.BaseMapper;
import com.harris.double_db.entity.MyUserTwo;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Author: he changjie on 2019/1/3
 * @Description:
 */
@Repository
public interface MyTwoMapper extends BaseMapper {
    /**
     * 2
     * @return
     */
    List queryAll2();
}

9、编写mybatis映射文件

因为使用了多数据源,无法在application中配置mybatis的xml路径,所以在项目中必须将xml在resources下路径与src中mapper的路径相同。

在resources下新建com.harris.double_db.mapper路径的包,再分别新建source1、source2两个包

在source1下新建MyOneMapper.xml






    
    

在source2下新建MyTwoMapper.xml






    
    

10、编写service

新建UserService.java

package com.harris.double_db.services;

import com.harris.double_db.entity.MyUserOne;
import com.harris.double_db.entity.MyUserTwo;
import com.harris.double_db.mapper.source1.MyOneMapper;
import com.harris.double_db.mapper.source2.MyTwoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: he changjie on 2019/1/3
 * @Description:
 */
@Service
public class UserService {
    @Autowired
    MyOneMapper myOneMapper;
    @Autowired
    MyTwoMapper myTwoMapper;

    /**
     * 使用mybatis的xml进行查询
     * @return
     */
    public Map findAll(){
        List ones = myOneMapper.queryAll1();
        List twos = myTwoMapper.queryAll2();
        Map map=new HashMap<>(2);
        map.put("one",ones);
        map.put("two",twos);
        return map;
    }

    /**
     * 使用mybatis的通用mapper进行查询
     * @return
     */
    public Map findAllByBaseMapper(){
        Example exampleOne = new Example(MyUserOne.class);
        Example.Criteria criteriaOne = exampleOne.createCriteria();
        criteriaOne.andBetween("age",10,30);
        List myUserOnes = myOneMapper.selectByExample(exampleOne);
        Example exampleTwo = new Example(MyUserTwo.class);
        Example.Criteria criteriaTwo = exampleTwo.createCriteria();
        criteriaTwo.andBetween("age",10,30);
        List myUserTwos = myTwoMapper.selectByExample(exampleTwo);
        Map map=new HashMap<>(2);
        map.put("one",myUserOnes);
        map.put("two",myUserTwos);
        return map;
    }
}

11、编写controller

本文为方便演示,将controller写在application中,各位小伙伴切勿模仿

package com.harris.double_db;

import com.harris.double_db.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@SpringBootApplication
@RestController
public class DoubleDbApplication {

    public static void main(String[] args) {

        SpringApplication.run(DoubleDbApplication.class, args);
        System.out.println(".................server running.................");
    }

    @Autowired
    UserService userService;

    @RequestMapping(value = "/method1",method = RequestMethod.GET)
    public Map method1(){
        return userService.findAll();
    }

    @RequestMapping(value = "/method2",method = RequestMethod.GET)
    public Map method2(){
        return userService.findAllByBaseMapper();
    }

}

12、启动项目

使用浏览器进行访问,我们看到页面显示数据都两个数据源下的内容,大功告成!

2019-01-11 11:12:57.639  INFO 13168 --- [  restartedMain] b.c.e.u.UndertowEmbeddedServletContainer : Undertow started on port(s) 8080 (http)
2019-01-11 11:12:57.644  INFO 13168 --- [  restartedMain] c.harris.double_db.DoubleDbApplication   : Started DoubleDbApplication in 3.411 seconds (JVM running for 4.072)
.................server running.................

在浏览器输入http://localhost:8080/method1,页面显示如下图所示(使用mybatis的sql xml进行的查询)

spring boot多数据源整合mybatis通用mapper_第4张图片

在浏览器输入http://localhost:8080/method2,页面显示如下图所示(使用mybatis的通用mapper进行的查询)

spring boot多数据源整合mybatis通用mapper_第5张图片

13、项目源码下载路径

https://gitee.com/jie_harris/multiple-data-source.git

 

手编不易,转载或参考请注明链接,谢谢!

你可能感兴趣的:(项目搭建,spring,cloud,微服务实战)