Mybatis Reverse Engineering (java configuration implementation)

Posted by davestewart on Sun, 16 Jan 2022 21:53:11 +0100

Various reverse engineering articles viewed on the Internet found that they are basically implemented in the way of xml configuration. Now basically, projects use java classes to realize xml configuration. Therefore, in sorting out the implementation methods of pure java annotations, we must pay attention to that the implementation methods of java codes are based on xml. Therefore, at the beginning of this paper, we add xml annotations for comparison,

xml annotation
<?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>
        <!-- Import profile -->  
    <properties resource="generator.properties"/> 
        <!-- Database driver location --> 
    <classPathEntry location="${classPath}" />
        <!-- One database one context, targetRuntime:This property specifies the runtime environment for the generated code ,MyBatis3:*This is the default*,MyBatis3Simple Do not generate Example query(Avoid subsequent table settings)     defaultModelType:How to generate entity classes,flat It is recommended to generate an entity class for each table--> 
<context id="mysqlTables" targetRuntime="com.practice.mybatis.TkMyBatis3Impl" defaultModelType="flat">
        <!-- notes  type Represents a custom comment-->
    <commentGenerator type="com.practice.mybatis.MyCommentGenerator">
        <!-- Encoding of the generated file (eclipse When plug-in, there is no egg here. You need to eclipse Of the root directory eclipse.ini Finally add -Dfile.encoding=UTF-8  )-->
        <property name="javaFileEncoding" value="UTF-8"/>
        <!-- Uncomment -->
        <property name="suppressAllComments" value="false" />
        <property name="addRemarkComments" value="true"/>
        <!-- Generate comment generation timestamp -->
        <property name="suppressDate" value="true" />
        <!-- When the table name or field name is SQL Keyword, you can set this property to true,MBG Table or field names are automatically added**Separator**  -->    
        <property name="autoDelimitKeywords" value="true"></property>
        <!-- because beginningDelimiter and endingDelimiter The default value for is double quotation marks("),stay Mysql You can't write this in, so you have to change these two default values to**back quote (`)** -->
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>  
    </commentGenerator>
        <!-- Database url,User name and password --> 
    <jdbcConnection driverClass="${jdbc.driver}" 
        connectionURL="${jdbc.url}" 
        userId="${jdbc.user}" 
        password="${jdbc.password}">
    </jdbcConnection>
        <!-- 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>
        <!-- Package name and location of the build model -->
    <javaModelGenerator targetPackage="${package_domain}" targetProject="${project}">
        <!-- Add a new layer under the current path schema,eg: fase route com.goshop.domain", true:com.goshop.domain".[schemaName] -->
        <property name="enableSubPackages" value="false" />
        <!-- For string Fields of type set When trim call -->
        <property name="trimStrings" value="true" />
    </javaModelGenerator>
        <!-- Generated mapping package name and location -->
    <sqlMapGenerator targetPackage="${package_mapper}"  targetProject="${resource}">
        <!-- Add a new layer under the current path schema,eg: fase route com.goshop.domain", true:com.goshop.domain".[schemaName] -->
        <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
        <!-- generate DAO Package name and location of type 1,ANNOTATEDMAPPER Annotation form 2 XMLMAPPER xml Configuration file form-->
    <javaClientGenerator type="XMLMAPPER" targetPackage="${package_dao}"  targetProject="${project}">
        <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
        <!-- Generate those tables tableName Table name mapperName generate dao The name of the, domainObjectName Should apply to database tables javaBean Class name, enable*ByExample Generate example class -->
        <!-- <table tableName="sys_user" domainObjectName="SysUser" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> -->
            <!-- Generate, do not ignore columns bean field   
            <ignoreColumn column="FRED" />-->  
            <!-- Specifies the of the column java data type   
            <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />-->  
        <table tableName="%" mapperName="{0}DAO">
            <columnOverride column="remarks" jdbcType="VARCHAR" />
        </table>
</context>
</generatorConfiguration>

preparation in advance

First, pom adds dependencies and plug-ins

<dependencies>
    <dependency>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-core</artifactId>
        <version>1.3.7</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
            </configuration>
        </plugin>
    </plugins>
</build>

mybatis-generator-core

MyBatisGenerator

Mybatis generator is the main interface. When using it, you only need to create a class instance and call the generate() method. A large number of properties are built in the class

/** Custom configuration class */
private Configuration configuration;

/** Callback */
private ShellCallback shellCallback;

/**Generate java files */
private List<GeneratedJavaFile> generatedJavaFiles;

/** Generate xml file */
private List<GeneratedXmlFile> generatedXmlFiles;

/** Alarm information */
private List<String> warnings;

/** Project information */
private Set<String> projects;

/**
 * Constructs a MyBatisGenerator object.
 * 
 * @param configuration
 *            The configuration for this invocation
 * @param shellCallback
 *            an instance of a ShellCallback interface. You may specify
 *            <code>null</code> in which case the DefaultShellCallback will
 *            be used.
 * @param warnings
 *            Any warnings generated during execution will be added to this
 *            list. Warnings do not affect the running of the tool, but they
 *            may affect the results. A typical warning is an unsupported
 *            data type. In that case, the column will be ignored and
 *            generation will continue. You may specify <code>null</code> if
 *            you do not want warnings returned.
 * @throws InvalidConfigurationException
 *             if the specified configuration is invalid
 */
public MyBatisGenerator(Configuration configuration, ShellCallback shellCallback,
        List<String> warnings) throws InvalidConfigurationException {
    super();
    if (configuration == null) {
        throw new IllegalArgumentException(getString("RuntimeError.2")); //$NON-NLS-1$
    } else {
        this.configuration = configuration;
    }

    if (shellCallback == null) {
        this.shellCallback = new DefaultShellCallback(false);
    } else {
        this.shellCallback = shellCallback;
    }

    if (warnings == null) {
        this.warnings = new ArrayList<String>();
    } else {
        this.warnings = warnings;
    }
    generatedJavaFiles = new ArrayList<GeneratedJavaFile>();
    generatedXmlFiles = new ArrayList<GeneratedXmlFile>();
    projects = new HashSet<String>();

    this.configuration.validate();
}

The constructor method provides only one construct, passing in a construct of three parameters So this article only focuses on these three attributes

Configuration

/** The contexts. */
private List<Context> contexts;

/** The class path entries. */
private List<String> classPathEntries;

Context

It provides a large number of configuration classes, including JDBC connection configuration class, Sql mapping configuration class, Java model generation configuration class, etc. for specific configuration, you should refer to the source code. This paper mainly provides a basic generation method

/**
 * The Class Context.
 *  * @author Jeff Butler
 */
public class Context extends PropertyHolder {
    
    /** The id. */
    private String id;

    /** The jdbc connection configuration. */
    private JDBCConnectionConfiguration jdbcConnectionConfiguration;
    
    private ConnectionFactoryConfiguration connectionFactoryConfiguration;

    /** The sql map generator configuration. */
    private SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration;

    /** The java type resolver configuration. */
    private JavaTypeResolverConfiguration javaTypeResolverConfiguration;

    /** The java model generator configuration. */
    private JavaModelGeneratorConfiguration javaModelGeneratorConfiguration;

    /** The java client generator configuration. */
    private JavaClientGeneratorConfiguration javaClientGeneratorConfiguration;

    /** The table configurations. */
    private ArrayList<TableConfiguration> tableConfigurations;

    /** The default model type. */
    private ModelType defaultModelType;

    /** The beginning delimiter. */
    private String beginningDelimiter = "\""; //$NON-NLS-1$

    /** The ending delimiter. */
    private String endingDelimiter = "\""; //$NON-NLS-1$

    /** The comment generator configuration. */
    private CommentGeneratorConfiguration commentGeneratorConfiguration;

    /** The comment generator. */
    private CommentGenerator commentGenerator;

    /** The plugin aggregator. */
    private PluginAggregator pluginAggregator;

    /** The plugin configurations. */
    private List<PluginConfiguration> pluginConfigurations;

    /** The target runtime. */
    private String targetRuntime;

    /** The introspected column impl. */
    private String introspectedColumnImpl;

    /** The auto delimit keywords. */
    private Boolean autoDelimitKeywords;
    
    /** The java formatter. */
    private JavaFormatter javaFormatter;
    
    /** The xml formatter. */
    private XmlFormatter xmlFormatter;
  ...(ellipsis)

defaultModelType: Specifies the policies for entity generation, and each one corresponds to a rule

  • Hierarchical: with a primary key, generate a separate primary key entity class, with blob and text types, generate a separate entity class containing all blob and text fields, and generate an entity with other attributes (hierarchical modelrules)
  • conditional (default): it is basically the same as hierarchical, except that when the table has only one attribute, only one basic entity class is generated (even if this field is a primary key, no primary key entity class is generated) (ConditionalModelRules)
  • flat: only one entity class is generated for each table. This entity class contains all the fields in the table (FlatModelRules)

Test implementation

package com.huntkey.rx.sceo.generator;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.*;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.util.ArrayList;
import java.util.List;

/**
 * @description: mybatis Reverse engineering test
 * @author: wangml
 * @date: 2021/7/24 09:31
 */
public class MybatisGeneratorTest {

    public static final String PROJECT_SOURCES_ROOT_DIR = "D:\\workspace\\HuntKey\\springbootDemo\\src\\main\\java";
    public static final String PROJECT_RESOURCES_ROOT_DIR = "D:\\workspace\\HuntKey\\springbootDemo\\src\\main\\resources";

    public static void main(String[] args) throws Exception {
        // Warning message
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;

        Configuration config = new Configuration();
        // Mybatis entity generation policy (CONDITIONAL)
        Context context = new Context(ModelType.CONDITIONAL);
        context.setId("myTest");

        //Whether to generate comments of tables and columns in the database into the entity
        CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration();
        // addRemarkComments is an existing attribute of the CommentGenerator, but it is not declared in the java class. You should open it on demand (you can't define an nonexistent attribute)
        commentGeneratorConfiguration.addProperty("addRemarkComments", "true");
        context.setCommentGeneratorConfiguration(commentGeneratorConfiguration);

        //Configure database connection
        JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
        jdbcConnectionConfiguration.setDriverClass("com.mysql.cj.jdbc.Driver");
        jdbcConnectionConfiguration.setConnectionURL("jdbc:mysql://localhost:3306/sceo?useSSL=true");
        jdbcConnectionConfiguration.setUserId("root");
        jdbcConnectionConfiguration.setPassword("root");
        context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);

        //Configure entity class generation policy
        JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
        // Specify the parent class inherited by the entity (the properties of the parent class should exist in the table)
//        javaModelGeneratorConfiguration.addProperty("rootClass", "com.huntkey.rx.sceo.core.repository.entity.ResourceEntity");
        //Specifies the package name to which the entity class belongs
        javaModelGeneratorConfiguration.setTargetPackage("com.huntkey.rx.sceo.entity");
        //Specifies the src directory for the project
        javaModelGeneratorConfiguration.setTargetProject(PROJECT_SOURCES_ROOT_DIR);
        context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);

        //Configure Sql file generation policy
        SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
        sqlMapGeneratorConfiguration.setTargetPackage("mapper");
        sqlMapGeneratorConfiguration.setTargetProject(PROJECT_RESOURCES_ROOT_DIR);
        context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);

        //Configure generation policies for DAO interfaces
        JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
        //Interface implementation methods: XMLMAPPER, MIXEDMAPPER, ANNOTATEDMAPPER
        javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
//        javaClientGeneratorConfiguration.addProperty("rootInterface", "com.huntkey.rx.sceo.core.repository.dao.Mapper");
        javaClientGeneratorConfiguration.setTargetPackage("com.huntkey.rx.sceo.dao");
        javaClientGeneratorConfiguration.setTargetProject(PROJECT_SOURCES_ROOT_DIR);
        context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);

        //Generate additional rule configurations for entities
        TableConfiguration tableConfiguration = new TableConfiguration(context);
        tableConfiguration.setDomainObjectName("User");
        //Whether to directly use the database column name as the attribute name. If false, it will turn to hump
        tableConfiguration.setTableName("user_test");
        context.addTableConfiguration(tableConfiguration);

        config.addContext(context);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        System.out.println("success");
    }
}

Run main to get the generated java file in the corresponding directory

summary

  • Both the implementation method of xml annotation and the method of java configuration can realize functions (there are many blogs in the way of xml)
  • Understanding the underlying implementation can facilitate us to control the code and use it with ease

Reference article:
https://www.cnblogs.com/liaojie970/p/8029000.html
https://blog.csdn.net/wl_627292578/article/details/54895587

Topics: Java Mybatis