Springboot integrates general Mapper and Pagehelper to realize mybatis+Druid multi-data source configuration

Keywords: Mybatis MySQL Druid Java

1. As a supplement to the previous one, this article can be referred to.

    https://my.oschina.net/swiftloop/blog/1031404

2. Realization

    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>com.sorata.datasource</groupId>
	<artifactId>mybatis-pagehelper-mapper</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>mybatis-pagehelper-mapper</name>
	<description>Integrate mybatis Multiple Data Sources and Paging Plug-ins and Universal mapper Use</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
        <!-- Here is the package for configuring master and slave libraries when generating different databases dao,mapper,entity Need to change this package, or directly in generator.xml Hard Coding Under Files-->
		<!--Store generated dao and entity-->
		<targetJavaProject>${basedir}/src/main/java</targetJavaProject>
		<!--end-->
		<!--  XML Generation path  -->
		<targetResourcesProject>${basedir}/src/main/resources</targetResourcesProject>
		<targetXMLPackage>mapper/master</targetXMLPackage>
		<!--end-->
		<!--Deposit dao Package-->
		<targetMapperPackage>com.sorata.datasource.dao.master</targetMapperPackage>
		<!--end-->
		<!--Deposit entity Package-->
		<targetModelPackage>com.sorata.datasource.entity.master</targetModelPackage>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

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

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.29</version>
		</dependency>

		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>

		<dependency>
			<groupId>tk.mybatis</groupId>
			<artifactId>mapper-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-commons</artifactId>
			<version>1.13.1.RELEASE</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>

			<plugin>
				<groupId>org.mybatis.generator</groupId>
				<artifactId>mybatis-generator-maven-plugin</artifactId>
				<version>1.3.2</version>
				<configuration>
					<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
					<overwrite>true</overwrite>
					<verbose>true</verbose>
				</configuration>
				<dependencies>
					<dependency>
						<groupId>mysql</groupId>
						<artifactId>mysql-connector-java</artifactId>
						<version>5.1.30</version>
					</dependency>
					<dependency>
						<groupId>tk.mybatis</groupId>
						<artifactId>mapper</artifactId>
						<version>3.4.0</version>
					</dependency>
				</dependencies>
			</plugin>

		</plugins>
	</build>


</project>

    2)generator.xml  

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <properties resource="application.yml"/>

    <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <!-- Here is a class under the project package-->
            <property name="mappers" value="com.sorata.datasource.webmvc.MyMapper"/>
        </plugin>

        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/test1"
                        userId="root"
                        password="root">
        </jdbcConnection>

        <javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/>

        <sqlMapGenerator targetPackage="${targetXMLPackage}"  targetProject="${targetResourcesProject}"/>

        <javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}" type="XMLMAPPER" />

        <table tableName="test" domainObjectName="CustomTest">
            <!--mysql To configure-->
            <generatedKey column="id" sqlStatement="Mysql" identity="true"/>
            <!--oracle To configure-->
            <!--<generatedKey column="id" sqlStatement="select SEQ_{1}.nextval from dual" identity="false" type="pre"/>-->
        </table>
    </context>
</generatorConfiguration>

    3)MyMapper.java

package com.sorata.datasource.webmvc;

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

/**
 * Created by: Sorata 17/4/12 12:03 p.m.
 */
public interface MyMapper<T> extends Mapper<T>,MySqlMapper<T> {
}

    4)MasterDataSourceConfig.java

package com.sorata.datasource.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

/**
 * Created by :  Sorata   2017/6/27 0027 3:56. PM
 */
@Configuration
@MapperScan(basePackages = MasterDataSourceConfig.MASTER_PACKAGE,sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    private Logger logger = LoggerFactory.getLogger(MasterDataSourceConfig.class);


    static final String  MASTER_PACKAGE = "com.sorata.datasource.dao.master";
    private static final String MASTER_MAPPER_LOCAL = "classpath:mapper/master/*.xml";


    /** Configure a main library
     * @return  DruidDataSource
     */
    @Bean(name = "masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "druid.datasource")
    public DruidDataSource masterDruidDataSource(){
        return new DruidDataSource();
    }


    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(){
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(masterDruidDataSource());

        try {
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MASTER_MAPPER_LOCAL));
            return sessionFactoryBean.getObject();
        } catch (Exception e) {
            logger.error("Configuring the main library SqlSessionFactory Failure error:{}",e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager(){
        return new DataSourceTransactionManager(masterDruidDataSource());
    }

}

    5)CustomDataSourceConfig.java

package com.sorata.datasource.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
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;

/**
 * Created by :  Sorata   2017/6/27 0027 3:56. PM
 */
@Configuration
@MapperScan(basePackages = CustomDataSourceConfig.CUSTOM_PACKAGE,sqlSessionFactoryRef = "customSqlSessionFactory")
public class CustomDataSourceConfig {

    private Logger logger = LoggerFactory.getLogger(CustomDataSourceConfig.class);


    static final String CUSTOM_PACKAGE = "com.sorata.datasource.dao.custom";
    private static final String CUSTOM_MAPPER_LOCAL = "classpath:mapper/custom/*.xml";

    /** Configure a slave Library
     * @return DruidDataSource
     */
    @Bean(name = "customDataSource")
    @ConfigurationProperties(prefix = "custom.datasource")
    public DruidDataSource customDruidDataSource(){
        return new DruidDataSource();
    }

    @Bean(name = "customSqlSessionFactory")
    public SqlSessionFactory customSqlSessionFactory(){
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(customDruidDataSource());

        try {
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(CUSTOM_MAPPER_LOCAL));
            return sessionFactoryBean.getObject();
        } catch (Exception e) {
            logger.error("Configuring slave Libraries SqlSessionFactory Failure error:{}",e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Bean(name = "customTransactionManager")
    public DataSourceTransactionManager customTransactionManager(){
        return new DataSourceTransactionManager(customDruidDataSource());
    }

}

    6)DataSourcesAutoConfiguration.java

package com.sorata.datasource.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import javax.annotation.Resource;


/**
 * Created by :  Sorata   2017/6/27 0027 1:38. PM
 */
@Configuration
@EnableTransactionManagement
@ConditionalOnBean({MasterDataSourceConfig.class,CustomDataSourceConfig.class})
public class DataSourcesAutoConfiguration  implements TransactionManagementConfigurer{

    @Resource
    private MasterDataSourceConfig masterDataSourceConfig;

    @Resource
    private CustomDataSourceConfig customDataSourceConfig;

//  Configuring Distributed Transaction Management 
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {

        return  new  ChainedTransactionManager(masterDataSourceConfig.masterTransactionManager(),customDataSourceConfig.customTransactionManager());
    }

}

Note: This solves the problem of using annotations to display transaction managers annotated from the repository when there are two transaction managers.

7) Druid. Note the addition of @ServletComponentScan to the startup class

package com.sorata.datasource.config;

import com.alibaba.druid.support.http.StatViewServlet;

import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

/**
 * Created by: guobo 17/1/19 5:20 p.m.
 *
 * alibaba druid Page monitoring configuration accesses URL http://localhost:8080/project name/druid/index.html
 *
 * When using spring boot, you need to use the @ServletComponentScan annotation in the startup class
 */

@SuppressWarnings("serial")
@WebServlet(urlPatterns = "/druid/*",initParams = {
        //@ WebInitParam (name = allow, value = 127.0.0.1, 192.168.1.142), //whitelist
        @WebInitParam(name = "deny",value = "126.12.22.1"),//Blacklist (deny takes precedence over allow when there is common ground)
        @WebInitParam(name="loginUsername",value="admin"),// User name
        @WebInitParam(name="loginPassword",value="123456"),// Password
        @WebInitParam(name="resetEnable",value="false")// Disable "Reset All" functionality on HTML pages


})


public class DruidStateViewServlet extends StatViewServlet {
}
package com.sorata.datasource.config;

import com.alibaba.druid.support.http.WebStatFilter;

import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * Created by: guobo 17/1/19 5:27 p.m.
 *
 * alibaba druid Filtration
 */
@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*",
        initParams={
                @WebInitParam(name="exclusions",value="*.mp4,*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// Ignore resources
        })
public class DruidStatFilter extends WebStatFilter {

}

    8)application.yml

druid:
  datasource:
    name: mydatabases
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    filters: stat,wall,log4j
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: false  #If it is oracle, it can be set to true, if it is mysql, it can be set to false database with more sub-database and sub-table. It is recommended that it be configured as false.
    maxOpenPreparedStatements: 20

custom:
  datasource:
      name: mydatabases2
      url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: root
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.jdbc.Driver
      filters: stat,wall,log4j
      maxActive: 20
      initialSize: 1
      maxWait: 60000
      minIdle: 1
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: select 'x'
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: false  #If it is oracle, it can be set to true, if it is mysql, it can be set to false database with more sub-database and sub-table. It is recommended that it be configured as false.
      maxOpenPreparedStatements: 20


pagehelper:
    helperDialect: mysql
    reasonable: true
    supportMethodsArguments: true
    params: count=countSql

3. Summary

After introducing general Mapper dependencies and PageHelper dependencies, they are all automatically configured. PageHeler has automatic configuration on multiple data sources, so it is not necessary to add plug-ins when configuring SqlSession Factory. If added, the exception of adding multiple paging plug-ins will be reported. And the manager that uses ChainedTransaction Manager to manage multiple transaction managers does not need to display annotated slave libraries anymore.

Attachment:

    Pagehelper:https://github.com/pagehelper/Mybatis-PageHelper

    Mapper:http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/2.Integration.md

This project: http://git.oschina.net/lencer93/mybatis-pagehelper-mapper

Posted by Assim on Mon, 11 Feb 2019 08:45:17 -0800