SpringBoot 2.0 + Mybatis Generator + IDEA Making Multiple Data Sources

Posted by chico1st on Tue, 10 Sep 2019 10:30:05 +0200

SpringBoot 2.0 + Mybatis + Mybatis Generator + Multiple Data Sources + IDEA

Make complaints

Yesterday, I found a "complete" version of the Internet using SpringBoot 2.0 + Mybatis to achieve multi-data sources. As a result, there is a lack of some code, which is very miserable and wastes too much time. After finding N tutorials, I finally succeeded in integration and quickly sorted out the article.

Development environment and technology stack

With IDEA, the following functional points are integrated: SpringBoot 2.0 + Mybatis + Mybatis Generator + XML
Interacting with databases in the form of XML, rather than annotations, is it convenient to encounter complex SQL statements or XML after a project?

Project Production Steps

  1. The process of creating SpringBoot 2.0 projects using IDEA is skipped

  2. All the code of 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>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.8.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.xdf</groupId>
        <artifactId>multd</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>multd</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-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>2.1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </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>
                    <configuration>
                        <verbose>true</verbose>
                        <overwrite>true</overwrite>
                    </configuration>
                </plugin>
    
    
            </plugins>
        </build>
    
    </project>
    
    
  3. Explain project structure

    Originally, I wanted to mark the role of each package and file in the picture, and see too much, it's better to express it in words. Controller stores controller classes, com.xdf.multd.dao.test1 and com.xdf.multd.dao.test2 respectively store Dao classes corresponding to two databases, com.xdf.multd.datasource stores database connections corresponding to two databases, and ORM classes corresponding to two database tables are stored in package com.xdf.multd.model, com.xdf.multd.s. Ervice is naturally the service layer.

    Following is a description of the files in the resources directory:

    The mapper is the location where the mapper file generated by Mybatis Generator is stored. After generation, the corresponding copies are copied to mappers.test1 or mappers.test2. The following three files, application.yml, application-dev.yml and application-mult.yml, are multi-environment configurations. Generator Config. XML is the relevant parameter of Mybatis Generator. mybatis-config.xml is the corresponding relationship of data types when mapping ORM. The last mysql-connector-java-5.1.34.jar is the driver used when Mybatis Generator links to database.
    [Img-SKrEJcJY-15681031769 (D: Java Document Java Material SpringBoot 2.0 Data Sources Project Structure Interpretation)]

  4. All the code of application.yml:

    spring:
      profiles:
        active: mult
    

    All the code of application-mult.yml:

    server:
      port: 8083
    
    # Configuration of mybatis generator
    mybatis:
      config-location: classpath:mybatis-config.xml
      mapper-locations: classpath:mapper/*.xml
      type-aliases-package: com.xdf.multd.model
    
    
    spring:
      datasource:
        test1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          jdbc-url: jdbc:mysql://localhost:3306/femis?userUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
          username: root
          password: chanchaw
        test2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          jdbc-url: jdbc:mysql://localhost:3306/femisimg?userUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
          username: root
          password: chanchaw
    
  5. All the code of mybatis-config.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="callSettersOnNulls" value="true"/>
            <setting name="cacheEnabled" value="true"/>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="true"/>
            <setting name="multipleResultSetsEnabled" value="true"/>
            <setting name="useColumnLabel" value="true"/>
            <setting name="useGeneratedKeys" value="false"/>
            <setting name="autoMappingBehavior" value="PARTIAL"/>
            <setting name="defaultExecutorType" value="SIMPLE"/>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <setting name="localCacheScope" value="SESSION"/>
            <setting name="jdbcTypeForNull" value="NULL"/>
        </settings>
        <typeAliases>
            <typeAlias alias="Integer" type="java.lang.Integer" />
            <typeAlias alias="Long" type="java.lang.Long" />
            <typeAlias alias="HashMap" type="java.util.HashMap" />
            <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
            <typeAlias alias="ArrayList" type="java.util.ArrayList" />
            <typeAlias alias="LinkedList" type="java.util.LinkedList" />
        </typeAliases>
    </configuration>
    
    

    The full code of generatorConfig.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">
    <!-- Configuration Generator -->
    <generatorConfiguration>
    
        <!--classPathEntry:Database JDBC drive,Change to your own drive location. -->
        <!--<classPathEntry location="E:\IdeaProjects\mysql-connector-java-5.1.47.jar"/>-->
        <classPathEntry location="D:\Java\ideaProject\multd\src\main\resources\mysql-connector-java-5.1.34.jar"/>
    
        <!-- One database one context,defaultModelType="flat" Big data fields, no tables -->
        <context id="MysqlTables" targetRuntime="MyBatis3Simple" defaultModelType="flat">
    
            <!-- Automatic recognition of database keywords, default false,If set to true,according to SqlReservedWords List of keywords defined in the database; generally keep the default value and encounter database keywords( Java Keyword, using columnOverride cover -->
            <property name="autoDelimitKeywords" value="true"/>
    
            <!-- Generated Java Coding of files -->
            <property name="javaFileEncoding" value="utf-8"/>
    
            <!-- beginningDelimiter and endingDelimiter: Symbols that specify a database for marking database object names, such as ORACLE It's double quotation marks. MYSQL The default is`Inverse quotation marks; -->
            <property name="beginningDelimiter" value="`"/>
            <property name="endingDelimiter" value="`"/>
    
            <!-- Format java Code -->
            <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
    
            <!-- Format XML Code -->
            <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
            <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
            <plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
    
            <!-- Notes -->
            <commentGenerator>
                <property name="suppressAllComments" value="true"/><!-- Whether to cancel the comment -->
                <property name="suppressDate" value="false"/> <!-- Whether to generate annotation generation timestamp-->
            </commentGenerator>
    
            <!-- jdbc Connect-->
            <!--<jdbcConnection driverClass="com.mysql.jdbc.Driver"-->
                            <!--connectionURL="jdbc:mysql://localhost:3306/femis?serverTimezone=UTC" userId="root"-->
                            <!--password="chanchaw"/>-->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                            connectionURL="jdbc:mysql://localhost:3306/femisimg?serverTimezone=UTC" userId="root"
                            password="chanchaw"/>
    
            <!-- Type Conversion -->
            <javaTypeResolver>
                <!-- Whether to use bigDecimal, false The following types can be automatically converted( Long, Integer, Short, etc.) -->
                <property name="forceBigDecimals" value="false"/>
            </javaTypeResolver>
    
            <!-- Generate Entity Class Address -->
            <javaModelGenerator targetPackage="com.xdf.multd.model" targetProject="src/main/java">
                <!-- Whether to let schema Suffixes for packages -->
                <property name="enableSubPackages" value="false"/>
                <!-- Remove the front and back spaces from the values returned from the database -->
                <property name="trimStrings" value="true"/>
            </javaModelGenerator>
    
            <!-- generate map.xml File Deposit Address -->
            <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
                <property name="enableSubPackages" value="false"/>
            </sqlMapGenerator>
    
            <!-- Generating interface dao -->
            <javaClientGenerator targetPackage="com.xdf.multd.dao" targetProject="src/main/java" type="XMLMAPPER">
                <property name="enableSubPackages" value="false"/>
            </javaClientGenerator>
    
            <!-- table There can be multiple,Tables in each database can be written in one table,tableName Represents the database table to match,It can also be found in tableName Use in attributes%Wildcards to match all database tables,Only matching tables generate files automatically enableSelectByPrimaryKey The corresponding configuration indicates whether the corresponding interface is generated or not. -->
            <table tableName="orderimg" enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"
                   enableSelectByPrimaryKey="true" enableUpdateByPrimaryKey="true"
                   enableDeleteByPrimaryKey="true">
                <property name="useActualColumnNames" value="true"/>
            </table>
    
        </context>
    </generatorConfiguration>
    
    
  6. Create the corresponding data source for the two databases. Both files are placed under com. xdf. multd. data source. The full code of the DataSource1Config pair is as follows:

    package com.xdf.multd.datasource;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    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.core.io.support.ResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = "com.xdf.multd.dao.test1", sqlSessionTemplateRef  = "test1SqlSessionTemplate")
    public class DataSource1Config {
    
        @Bean(name = "test1DataSource")
        @ConfigurationProperties(prefix = "spring.datasource.test1")
        @Primary
        public DataSource testDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "test1SqlSessionFactory")
        @Primary
        public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource);
            //Add an XML directory
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            try {
                bean.setMapperLocations(resolver.getResources("classpath*:mappers/test1/*.xml"));
                return bean.getObject();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
    
        }
    
        @Bean(name = "test1TransactionManager")
        @Primary
        public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
    
        @Bean(name = "test1SqlSessionTemplate")
        @Primary
        public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    
    }
    
    

    The full code of DataSource2Config is as follows:

    package com.xdf.multd.datasource;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.core.io.support.ResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = "com.xdf.multd.dao.test2", sqlSessionTemplateRef  = "test2SqlSessionTemplate")
    public class DataSource2Config {
    
        @Bean(name = "test2DataSource")
        @ConfigurationProperties(prefix = "spring.datasource.test2")
        public DataSource testDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "test2SqlSessionFactory")
        public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource);
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            try {
                bean.setMapperLocations(resolver.getResources("classpath*:mappers/test2/*.xml"));
                return bean.getObject();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    
        @Bean(name = "test2TransactionManager")
        public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
    
        @Bean(name = "test2SqlSessionTemplate")
        public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    
    }
    
    
  7. The rest of the work is to use Mybatis Generator to generate ORM classes and copy them to the corresponding directory, and manually make service classes and controllers for testing.

Topics: Mybatis Java Spring xml