Code generation tools

Although MyBatis is a simple framework to learn, configuring XML files is a rather tedious process, and there are many errors that are not easy to locate. When you have to generate a lot of objects in your work, there’s just too much repetitive effort to live for. Therefore, the MyBatis Generator was officially developed. It requires only a small amount of simple configuration, can complete a large number of table to Java object generation work, has zero error and fast advantages, free developers to focus more on the development of business logic. MyBatis-Generator is a code generation tool provided by MyBatis. This helps us generate persistent objects (also known as Models and PO) for database tables, interfaces to manipulate the database (DAOs), and mapper (in XML form or annotated form) for simple SQL. Its official website is mybatis.org/generator/

10.1 introduced

Since you need to use MyBatis-Generator, MyBatis and some kind of database must be used in your project, and these dependencies should already be configured in Maven. For example, in a POM file:

One is:

<! -- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupid>org.mybatis.spring.boot</groupid>
    <artifactid>mybatis-spring-boot-starter</artifactid>
    <version>xx.xx.xx</version>
</dependency>

<! -- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <version>xx.xx.xx</version>
</dependency>

<! Mybatis code automatic generator -->
<! -- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
    <groupid>org.mybatis.generator</groupid>
    <artifactid>mybatis-generator-core</artifactid>
    <version>xx.xx.xx</version>
</dependency>
Copy the code

Another way is:

<! -- -- -- > plugin
<plugins>
    <! -- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-maven-plugin -->
    <plugin>
        <groupid>org.mybatis.generator</groupid>
        <artifactid>mybatis-generator-maven-plugin</artifactid>
        <version>xx.xx.xx</version>
        <! -- Plugin Settings -->
        <configuration>
            <! Print execution log on console -->
            <verbose>true</verbose>
            <! Duplicate build overwrites previous files -->
            <overwrite>true</overwrite>
            <! Generatorconfig.xml (generatorconfig.xml)
            <! --<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>-->
        </configuration>
    </plugin>
</plugins>
Copy the code

10.2 Configuration File

MyBatis-Generator requires an XML configuration file to configure the various details of the generated code. For example, create a new mybatis-generator-config.xml configuration file in the resources directory of your project.

<generatorconfiguration>
    <! -- 0 or 1 -->
    <properties />
    <! -- 0 or 1 -->
    <classpathentry />
    <! -- one or more -->
    <context>
        <! -- JDBC connection -->
        <jdbcconnection>.</jdbcconnection>
        <! -- schema specifies the name of the database, tableName specifies the name of the corresponding database table.
        <table>.</table>
        <! - comments -- >
        <commentgenerator>.</commentgenerator>
        <! -- Type conversion -->
        <javatyperesolver>.</javatyperesolver>
        <! -- Generate entity class configuration -->
        <javamodelgenerator>.</javamodelgenerator>
        <! Create mapper.xml file configuration -->
        <sqlmapgenerator>.</sqlmapgenerator>
        <! Create mapper.java interface -->
        <javaclientgenerator>.</javaclientgenerator>
    </context>
</generatorconfiguration>
Copy the code

10.2.1 properties

Properties is used to load a configuration item or a configuration file, which can be referenced throughout the configuration file using ${propertyKey}, useful for JDBC and targetProject properties that need to be configured later. This element has two attributes that specify the address of the external configuration file. Only one of these attributes can be specified.

attribute instructions
resource The specifiedclasspathProperties file under.

Use a similarcom/myproject/generatorConfig.propertiesThe value of this property
url Specify a specific location on the file system.

For example file:///C:/myfolder/generatorConfig.properties

10.2.2 classPathEntry

Using the classPathEntry element, you can load additional dependencies as needed, where the location property indicates the full path of the JAR /zip package to be loaded.

<! Mysql > specify the location of the JDBC driver JAR package for the database driver
<classpathentry location=". / mysql connector - Java - 5.1.40. Jar" />
Copy the code

10.2.3 context elements

In the child element of generationConfiguration, context is the core element used to configure the environment that generates a set of objects. The context element has four attributes that can be configured:

attribute instructions
id Mandatory, context ID, to prompt when an error is generated;

Just make sure that the ids of multiple contexts are not duplicated.
defaultModelType Used to specify the style of the generated object
targetRuntime Used to specify the runtime environment for the generated code. This configuration affects the content of the generated DAO and mapper.xml

MyBatis3: the default value that generates content based on MyBatis3. X or higher, including XXXBySample;

MyBatis3Simple: similar to MyBatis3, except that XXXBySample is not generated;

There are other configurable values, as detailedwebsite
introspectedColumnImpl Class fully qualified name used forExtend the MBG

The context element has multiple child elements that need to be configured. Similarly, the children of the context must be configured as follows:

10.2.3.1 property

Use to specify attributes for code generation, or for other elements. Zero or more properties can be configured. Common property configurations are as follows:

<! -- Automatically identifies database keywords. Default is false. Generally, keep the default value. When a database keyword is encountered, it is overwritten according to the columnOverride attribute in the table element. If this parameter is set to true, delimit (delimit) the keywords according to the keyword list defined in SqlReservedWords. For delimiters, see beginningDelimiter and endingDelimiter Settings -->
<property name="autoDelimitKeywords" value="true" />

<! Code for the generated Java file -->
<property name="javaFileEncoding" value="UTF-8" />

<! -- Formatting 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" />

<! -- Specifies the symbol used to mark the name of the database object. For example, ORACLE is quoted in double quotes, MYSQL is quoted in backquotes by default. -->
<property name="beginningDelimiter" value="`" />
<property name="endingDelimiter" value="`" /> 
Copy the code

SqlReservedWords Keyword list

10.2.3.2 plugin

There can be zero or more plugins. The most common plugins are:

<! -- Make the generated Model implement Serializable interface
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

<! Override toString() for the generated Model -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />

<! Override equals() and hashCode() methods for the generated Model -->
<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin" />

<! Mysql > create paged SQL for mysql
<plugin type="generator.MysqlPaginationPlugin" />
Copy the code

10.2.3.3 commentGenerator

You can configure 0 or 1 to configure the generated comments. By default, comments are generated and information such as the time is added to the comments. However, the generated comment information has no value, so it is generally masked. The type attribute, which is used to specify its own annotation implementation class, inherits DefaultCommentGenerator to override some methods.

<commentgenerator>
	<! -- Generated comment does not contain time information, default is false --> 
	<property name="suppressDate" value="false" />
	<! -- Generated comments, time display format -->
	 <property name="dateFormat" value="yyyy-MM-dd" />
	<! Whether to remove automatically generated comments -->
	<property name="suppressAllComments" value="true" />
	<! Add comments to database -->
    <property name="addRemarkComments" value="true" />
</commentgenerator>
Copy the code

10.2.3.4 jdbcConnection

Specifies database connection information. This element is mandatory and can only have one, as follows:

<! ConnectionURL: JDBC connectionURL to access the database userId: userId to access the database password: password to access the database -->
<jdbcconnection driverclass="${spring.datasource.driverClassName}" connectionurl="${spring.datasource.url}" userid="${spring.datasource.username}" password="${spring.datasource.password}">
	
	<! Oracle database -->
	<property name="remarksReporting" value="true"></property>
	<! Mysql > select * from mysql;
    <property name="useInformationSchema" value="true"></property>
</jdbcconnection>
Copy the code

${propertyKey} contains the propertyValue of the referenced external configuration file.

10.2.3.5 javaTypeResolver

The value can be 0 or 1 to configure the type conversion rule for JDBC to Java. If the value is not configured, the default conversion rule is used:

  1. If accuracy >0 or length >18, java.math.bigDecimal is used
  2. If precision =0 and 10<= length <=18, java.lang.long is used
  3. If precision =0 and 5<= length <=9, java.lang.INTEGER is used
  4. If accuracy =0 and length <5, java.lang.short is used

10.2.3.6 javaModelGenerator

Java model generators, one or only configurable, are responsible for the generation of key classes (defaultModelType attributes of context elements), JavaBean entity classes, and query classes.

<! Create entity class location -->
<javamodelgenerator targetpackage="" targetproject="">
    
</javamodelgenerator>
Copy the code

JavaModelGenerator has two properties:

attribute instructions
targetPackage The name of the package in which the generated entity class is stored
targetProject Specify the target project path (An existing directory).

It can be an absolute or relative path (targetProject=” SRC /main/ Java “), and the generated content will be placed in the specified directory

You can also configure multiple property child elements within the javaModelGenerator element, as follows:

attribute The default value instructions
enableSubPackages false iftrue, MBG will be based oncatalogandschemaTo generate subpackages.

iffalseI’ll just use ittargetPackageProperties.
immutable false This property is used to configure whether the entity class attribute is mutable.

If set totrue, the constructor will be used and will not be generatedsetterMethods.

If it isfalse, entity class attributes can be changed.
trimStrings false Whether to perform database query resultstrimoperation
<javamodelgenerator targetpackage="org.dllwh.mybatis.model" targetproject="src\main\java">
    <property name="enableSubPackages" value="true" />
    <property name="trimStrings" value="true" />
</javamodelgenerator>
Copy the code

10.2.3.7 sqlMapGenerator

You can configure 0 or 1 XML file generators to generate SQL maps. After MyBatis3, you can use mapper. XML file + mapper interface, or just mapper interface + Annotation; Therefore, if the javaClientGenerator element is configured to generate XML, this element must be configured. This element has two attributes: targetPackage and targetProject

<sqlmapgenerator targetpackage="org.dllwh.dao.impl" targetproject="src/main/java">
    <! Set schema as a package name for a database configuration
    <property name="enableSubPackages" value="false" />
</sqlmapgenerator>
Copy the code
attribute instructions
targetPackage Generate mapper to store the package name, is generally placed under the package
targetProject Specify the target project path (An existing directory).

It can be an absolute or relative path (targetProject=” SRC /main/ Java “), and the generated content will be placed in the specified directory

Configuration example:

<sqlmapgenerator targetpackage="org.dllwh.mybatis.xml" targetproject="src\main\resources">
    <property name="enableSubPackages" value="true" />
</sqlmapgenerator>
Copy the code

10.2.3.8 javaClientGenerator

Used to configure the generation of Mapper interfaces, set 0 or 1. Note that if this element is not configured, the Mapper interface is not generated by default. It has three properties:

attribute instructions
type This property is used to select a predefined generator of client code (read: Mapper interface) that the user can customize

ANNOTATEDMAPPER: Created using Mapper interface +Annotation, no corresponding XML will be generated.

MIXEDMAPPER: With mixed configuration, Mapper interfaces are generated and annotations are appropriately added, but XML is generated in XML;

XMLMAPPER: Mapper interface is generated, and the interface is completely XML dependent.
targetPackage Generates the name of the package where the interface file is stored
targetProject Specify the target project path (An existing directory).

It can be an absolute or relative path (targetProject=” SRC /main/ Java “), and the generated content will be placed in the specified directory

Configuration example:

<javaclientgenerator type="XMLMAPPER" targetpackage="org.dllwh.dao" targetproject="src/main/java">

</javaclientgenerator>
Copy the code

10.2.3.9 table

Specify the database table, to generate which table, write which table, and the database corresponding, can not write wrong! A table element corresponds to a database table. If you want to generate code for multiple tables at the same time, you need to configure multiple table elements. Or you can set tableName to % to generate code for all tables.

attribute Whether must instructions
tableName Specify the name of the table to be generated. You can use SQL wildcards to match multiple tables. Note: Case sensitive
schema x The value is the database name, which is required for Oracle but not for mysql
catalog x Database catalog
domainObjectName x The class name of the generated entity object. If not specified, the name is automatically generated based on the table name
enableInsert x Specifies whether to generate insert statements. Default is true
enableSelectByPrimaryKey x Specifies whether to generate statements that query objects by primary key (that is, getById or GET). The default is true
enableSelectByExample x Specifies whether to generate dynamic queries. Default is true
enableUpdateByPrimaryKey x Specifies whether to generate statements based on the primary key update object. Default is true
enableDeleteByPrimaryKey x Specifies whether to generate statements based on primary key delete objects. The default is true
enableDeleteByExample x Specifies whether to generate a dynamic DELETE statement. The default is true
enableCountByExample x Specifies whether to generate a dynamic query total count statement (for paged total count queries). Default is true
enableUpdateByExample x Specifies whether to generate dynamic modification statements (only properties in an object that are not null). The default is true
delimitAllColumns x Sets whether all column names in the generated SQL are generated using identifiers

In addition, the table element can be configured with multiple child elements such as property and columnOverride. Example code is as follows:

<! -- Specifies whether only domain classes are generated. If true, only domain classes are generated. If sqlMapGenerator is also configured, only resultMap elements are generated in the mapper.xml file -->
<property name="modelOnly" value="false" />

<! -- classes that can be generated will inherit this class -->
<! -- <property name="rootClass" value=""/> -->

<! -- Add a parent interface to the generated class -->
<! -- <property name="rootInterface" value=""/> -->

<! If set to true, the generated model class will use the column name instead of using the camel name method.
<property name="useActualColumnNames" value="false" />

<! -- Method of generating primary key, if set, will generate a correct <selectKey> element in the generated <insert> element -->
<! -- <generatedKey column="id" sqlStatement="MySql" identity="true"/>-->
<generatedkey column="id" sqlStatement="SELECT LAST_INSERT_ID()" />

<! MBG will generate domain attributes based on the modified configuration. Column: the name of the column to be reset. ColumnOverride can be defined as multiple columnOverride elements in a table element.
<columnoverride column="show_status" javatype="" jdbctype="">
    <! -- Use the property attribute to specify the name of the property to be generated for the column -->
    <property name="property" value="showStatus" />

    <! -- javaType is used to specify the property type of the generated domain, using the fully qualified name of the type -->
    <property name="javaType" value="java.lang.Integer" />

    <! <property name="jdbcType" value=""/> -- jdbcType specifies the JDBC type of the column.
</columnoverride>
Copy the code

10.3 Configuration Example

Here is a simple example of MyBatis-Generator configuration

<! -- Config file header -->
<! -? The XML version = "1.0" encoding = "utf-8"? -->


<! GeneratorConfiguration --> generatorConfiguration
<! - the configuration reference http://mybatis.org/generator/configreference/xmlconfig.html-- >
<generatorconfiguration>
    <! -- Properties profile -->
	<properties resource="mybatis-generator.properties" />

	<context id="MySqlContext" targetruntime="MyBatis3">
		<property name="autoDelimitKeywords" value="true" />
        <! Code for the generated Java file -->
		<property name="javaFileEncoding" value="UTF-8" />
        <! -- Formatting 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" />
		<property name="beginningDelimiter" value="`" />
		<property name="endingDelimiter" value="`" />

		<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

		<commentgenerator>
			<property name="suppressDate" value="true" />
			<property name="dateFormat" value="yyyy-MM-dd" />
            <! -- Whether to remove automatically generated comments true: yes: false: no -->
			<property name="suppressAllComments" value="true" />
			<property name="addRemarkComments" value="true" />
		</commentgenerator>

        <! -- Configure database connection -->
		<jdbcconnection driverClass="${spring.datasource.driverClassName}" connectionURL="${spring.datasource.url}" userId="${spring.datasource.username}" password="${spring.datasource.password}" />
        
        <! Create class PO -->
		<javamodelgenerator targetpackage="${model.target.package}" targetproject="src/main/java">
            <! -- Allow subpackages -->
            <property name="enableSubPackages" value="false" />
            <! Add a constructor to Modal -->
            <property name="constructorBased" value="true" />
            <! SQL > select * from database;
			<property name="trimStrings" value="true" />
            <! Modal objects don't have setters, only constructors -->
            <property name="immutable" value="false" />
		</javamodelgenerator>

        <! Create Mapper interface location -->
		<sqlmapgenerator targetpackage="${mapper.target.package}" targetproject="src/main/java">
            <! Set schema as a package name for a database configuration
            <property name="enableSubPackages" value="false" />
		</sqlmapgenerator>

        <! Where Mapper XML is generated -->
		<javaclientgenerator type="XMLMAPPER" targetpackage="${dao.target.package}" targetproject="src/main/java">
            <! SQL > select 'schema' from 'oracle database';
            <property name="enableSubPackages" value="false" />
		</javaclientgenerator>

        <! Set the table name and entity class name of the database
		<property name="modelOnly" value="false" /><property name="useActualColumnNames" value="false" /><table tablename="sys_menu" enableinsert="true" enableselectbyprimarykey="true" enableselectbyexample="false" enableupdatebyprimarykey="true" enabledeletebyprimarykey="true" enabledeletebyexample="false" enablecountbyexample="false" enableupdatebyexample="false">
			
            <! If set to true, the generated model class will use the column name instead of using the camel name method.
			
		</table>
	</context>
</generatorconfiguration>
Copy the code

Mybatis -generator. Properties

#Mybatis Generator configuration
# Custom attributes - creator
custom.property.author=Alone tears without trace
# Custom Properties - Create mailbox
custom.property.email=[email protected]
# class root address
target.prefix=org.dllwh
Generate entity class address
model.target.package=org.dllwh.model
Create dao interface (mapper) address
dao.target.package=org.dllwh.dao
Generate mapper(XML) addresses
mapper.target.package=org.dllwh.dao.impl
# Database information
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring? useUnicode=true& characterEncoding=UTF-8& useSSL=true
spring.datasource.username=spring
spring.datasource.password=spring
Copy the code

10.4 the test class

To run it programmatically using Java code, you need to introduce dependencies in Maven’s POM file as per method 1. Then create a new Java class in the project with code similar to the following:

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorSqlmap {
	public void defaultCommentGenerator(a) throws Exception {
		// Warning message about MyBatis -generator execution
		List<string> warnings = new ArrayList<string>();
		// If the generated code is duplicated, override the original code
		boolean overwrite = true;
		// point to the reverse engineering configuration file
		String genCfg = "/generatorConfig.xml";
		// Read the MyBatis-Generator configuration file
		File configFile = new File(GeneratorSqlmap.class.getResource(genCfg).getFile());
		// Initialize the parser
		ConfigurationParser cp = new ConfigurationParser(warnings);
		// Call the configuration parser to create the configuration object
		Configuration config = cp.parseConfiguration(configFile);
		DefaultShellCallback callback = new DefaultShellCallback(overwrite);
		// Create a MyBatisGenerator object. The MyBatisGenerator class is the one that actually performs the generated action
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		// Execute the generated code
		myBatisGenerator.generate(null);

		// Displays a warning message
		warnings.forEach(warning -&gt; System.out.println(warning));
	}

	public static void main(String[] args) throws Exception {
		try {
			GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
			generatorSqlmap.defaultCommentGenerator();

		} catch(Exception e) { e.printStackTrace(); }}}Copy the code

10.5 Custom Extension

10.5.1 Customizing Comment Generation

CommentGenerator generated is controlled by the org.mybatis.generator.api.Com mentGenerator to, this is an interface, The MyBatis Generator’s default implementation class is org.. MyBatis Generator. Internal. DefaultCommentGenerator. When you configure the commentGenerator tag in GeneratorConfig. XML, by default, the job of generating comments is done by DefaultCommentGenerator. After running MyBatis-Generator, I can see the generated code and, well, the database comments are available, but the generated information is too obvious to look at. Looking at the source code, I find that the content is already written dead in DefaultCommentGenerator and there is no way to customize it.

Why don’t we just write our own class that implements the CommentGenerator interface and customize the comments we want? Looking at the CommentGenerator interface, you can see that there are a number of methods in there, including not only methods for generating Java entity comments, but also methods for generating comments in XML. So we define our own first class annotation CustomSQLCommentGenerator, inherit DefaultCommentGenerator, rewrite the way we need:

  1. In the project to create entity class CustomSQLCommentGenerator DefaultCommentGenerato inheritance

  2. Configure Generatorconfig.xml to set up our own comment generator:

    <! -? The XML version = "1.0" encoding = "utf-8"? -->
    
    
    <! GeneratorConfiguration --> generatorConfiguration
    <generatorconfiguration>
    	<properties resource="mybatis-generator.properties" />
    
    	<context id="MySqlContext" targetruntime="MyBatis3">
    		<! Comment address -->
    		<commentgenerator type="xx.xx.CustomSQLCommentGenerator">
    		</commentgenerator>
    	</context>
    </generatorconfiguration>
    Copy the code
  3. The main class MyBatis -generator is run again, and the class and field annotations are successfully generated

  4. It should also be added that the above example inherits the implementation of DefaultCommentGenerator and can also be implemented by implementing the CommentGenerator interface.

    package org.dllwh.template.database.mybatis.custom;
    
    import static org.mybatis.generator.internal.util.StringUtility.*;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Properties;
    import org.mybatis.generator.api.*;
    import org.mybatis.generator.api.dom.java.*;
    import org.mybatis.generator.api.dom.xml.XmlElement;
    import org.mybatis.generator.config.MergeConstants;
    
    public class CustomSQLCommentGenerator implements CommentGenerator {
    	The /** Property, the Property tag */ configured within the commentGenerator tag
    	private Properties properties;
    	/** Whether generated comments do not contain time information. The default is false */
    	private boolean suppressDate;
    	/** Whether to remove automatically generated comments */
    	private boolean suppressAllComments;
    	/** Whether to add comments in the database */
    	private boolean addRemarkComments;
    	/** In the generated comments, the time display format */
    	private SimpleDateFormat dateFormat;
    	/** Custom attributes - creator */
    	private String author;
    	/** Custom attributes - Create mailbox */
    	private String email;
    	/** Custom attributes - version */
    	private String version;
    	/** Custom attributes - Whether to add a get comment */
    	private boolean addGetComments;
    	/** Custom attributes - Whether to add a set annotation */
    	private boolean addSetComments;
    
    	public CustomSQLCommentGenerator(a) {
    		super(a); properties =new Properties();
    		suppressDate = false;
    		suppressAllComments = false;
    		addRemarkComments = true;
    	}
    
    	/** * Add this instance's property CommentGenerator configuration from any property in this configuration, this method will be called before any other method. * /
    	@Override
    	public void addConfigurationProperties(Properties properties) {
    		// Get the custom properties
    		this.properties.putAll(properties);
    
    		author = properties.getProperty("author"."");
    		email = properties.getProperty("email"."");
    		version = properties.getProperty("version"."V 1.0.1");
    		addGetComments = isTrue(properties.getProperty("addGetComments"))?true : false;
    		addSetComments = isTrue(properties.getProperty("addSetComments"))?true : false;
    
    		String dateFormatString = properties.getProperty("dateFormat"."yyyy-MM-dd HH:mm:ss");
    		if (stringHasValue(dateFormatString)) {
    			dateFormat = newSimpleDateFormat(dateFormatString); }}/** * Generate comments for xx.java file (model) properties. If comments are empty, do not add attributes. * /
    	@Override
    	public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    		if (suppressAllComments) {
    			return;
    		}
    		// Get column comments
    		String remarks = introspectedColumn.getRemarks();
    
    		// Enable comments with a value for comment in the database
    		if(addRemarkComments &amp; &amp; stringHasValue(remarks)) {// Split by newline character
    			String[] remarkLines = remarks.split(System.getProperty("line.separator"));
    			int length = remarkLines.length;
    			// If there are more than one line, wrap it
    			if (length &gt; 1) {
    				// Where the comment begins
    				field.addJavaDocLine("/ * *");
    				for (int i = 0; i &lt; length; i++) {
    					field.addJavaDocLine("*" + remarkLines[i]);
    				}
    				// End of comment
    				field.addJavaDocLine(" */");
    			} else {
    				field.addJavaDocLine("/ * *" + remarks + " */"); }}}/** * Static field of the entity class. If empty, no attribute is added. * /
    	@Override
    	public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return; }}/** * The class that created the table added the comment */
    	@Override
    	public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    		if(suppressAllComments || ! addRemarkComments) {return;
    		}
    		topLevelClass.addJavaDocLine("/ * *");
    		topLevelClass.addJavaDocLine("* Use today's best performance as tomorrow's latest starting point.. ~");
    		topLevelClass.addJavaDocLine("*");
    		topLevelClass.addJavaDocLine(" * Today the best performance as tomorrow newest starter!");
    		topLevelClass.addJavaDocLine("*");
    		topLevelClass.addJavaDocLine("* @ Class description: TODO(here a one-sentence description of what this class does)");
    
    		// Database table name
    		String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime();
    		// Get table comments
    		String tableRemarks = introspectedTable.getRemarks();
    
    		topLevelClass.addJavaDocLine("*");
    		topLevelClass.addJavaDocLine("* @ data table:" + tableName);
    
    		if (stringHasValue(tableRemarks)) {
    			topLevelClass.addJavaDocLine("*");
    			topLevelClass.addJavaDocLine("* @ datafile comment:");
    			String[] remarkLines = tableRemarks.split(System.getProperty("line.separator"));
    			for (String remarkLine : remarkLines) {
    				topLevelClass.addJavaDocLine("*" + remarkLine);
    			}
    		}
    		topLevelClass.addJavaDocLine("*");
    
    		if(stringHasValue(email) &amp; &amp; stringHasValue(author)) { topLevelClass.addJavaDocLine(" * @author : <a href="\&quot; mailto:&quot;" + email "\">" + author + "</a>");
    		} else if(stringHasValue(author) &amp; &amp; ! stringHasValue(email)) { topLevelClass.addJavaDocLine(" * @author : " + author);
    		} else if(stringHasValue(email) &amp; &amp; ! stringHasValue(author)) { topLevelClass.addJavaDocLine(" * @email : " + email);
    		}
    
    		topLevelClass.addJavaDocLine("* @ create time:" + getDateString());
    		topLevelClass.addJavaDocLine("* @ version:" + version);
    		topLevelClass.addJavaDocLine(" * @since : " + System.getProperty("java.version"));
    		topLevelClass.addJavaDocLine(" * @see <a href="\&quot; \&quot;"> ");
    		topLevelClass.addJavaDocLine(" */");
    	}
    
    	/** * Class annotations for Java classes */
    	@Override
    	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return; }}/** * Class annotations for Java classes */
    	@Override
    	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
    		if (suppressAllComments) {
    			return; }}/** * add comment */ for enumeration
    	@Override
    	public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    		StringBuilder sb = new StringBuilder();
    		innerEnum.addJavaDocLine("/ * *");
    		sb.append(introspectedTable.getFullyQualifiedTable());
    		innerEnum.addJavaDocLine(sb.toString());
    		addJavadocTag(innerEnum, false);
    		innerEnum.addJavaDocLine(" */");
    	}
    
    	/** * the database corresponds to the entity class Getter annotation */
    	@Override
    	public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    		if(suppressAllComments || ! addGetComments) {return;
    		}
    		method.addJavaDocLine("/ * *");
    
    		StringBuilder sb = new StringBuilder();
    		sb.append("*");
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append(introspectedColumn.getRemarks());
    			method.addJavaDocLine(sb.toString());
    			method.addJavaDocLine("*");
    		}
    
    		sb.setLength(0);
    		sb.append(" * @return ");
    		sb.append(introspectedColumn.getActualColumnName());
    
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append("-");
    			sb.append(introspectedColumn.getRemarks());
    
    		}
    		method.addJavaDocLine(sb.toString());
    		method.addJavaDocLine(" */");
    		return;
    	}
    
    	/** * the Setter method annotation for the entity class corresponding to the database */
    	@Override
    	public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    		if(suppressAllComments || ! addSetComments) {return;
    		}
    		method.addJavaDocLine("/ * *");
    		StringBuilder sb = new StringBuilder();
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append("*");
    			sb.append(introspectedColumn.getRemarks());
    			method.addJavaDocLine(sb.toString());
    			method.addJavaDocLine("*");
    		}
    
    		Parameter parm = method.getParameters().get(0);
    		sb.setLength(0);
    		sb.append(" * @param ");
    		sb.append(parm.getName());
    		if (stringHasValue(introspectedColumn.getRemarks())) {
    			sb.append("");
    			sb.append(introspectedColumn.getRemarks());
    		}
    		method.addJavaDocLine(sb.toString());
    		method.addJavaDocLine(" */");
    	}
    
    	Xxxmapper.java */
    	@Override
    	public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
    		if (suppressAllComments) {
    			return;
    		}
    		method.addJavaDocLine("/ * *");
    		method.addJavaDocLine("*" + method.getName());
    		method.addJavaDocLine("*");
    		List<parameter> parameters = method.getParameters();
    		parameters.forEach(parameter -&gt; method.addJavaDocLine(" * @param " + parameter.getName()));
    		method.addJavaDocLine("*");
    		// If there is a return type, add @return
    		String returnType = "void";
    
    		if(method.getReturnType() ! =null&amp; &amp; ! returnType.equals(method.getReturnType().toString())) { method.addJavaDocLine(" * @return ");
    		}
    		// addJavadocTag(method, false);
    		method.addJavaDocLine(" */");
    	}
    
    	/** * Comments the Java file at the top of the file, above the package. * /
    	@Override
    	public void addJavaFileComment(CompilationUnit compilationUnit) {
    		compilationUnit.addFileCommentLine("/ *");
    		compilationUnit.addFileCommentLine("*");
    		compilationUnit.addFileCommentLine("*" + compilationUnit.getType().getShortName() + ".java");
    		compilationUnit.addFileCommentLine("* Copyright(C) 2017-2020 XXX Company");
    		compilationUnit.addFileCommentLine("* ALL rights reserved.");
    		compilationUnit.addFileCommentLine("* @date " + getDateString() + "");
    		compilationUnit.addFileCommentLine("* /");
    	}
    
    	/** * The entity class is annotated with mapper. XML. The mapper class is not annotated, refer to DefaultCommentGenerator */ if necessary
    	@Override
    	public void addComment(XmlElement xmlElement) {
    		if (suppressAllComments) {
    			return; }}/** * annotates the first child node that calls this method as the root element. * /
    	@Override
    	public void addRootComment(XmlElement rootElement) {}/** * @ Method description: Returns a formatted date string to be included in Javadoc tags and XML comments. If you do not want the date, you can return NULL in these document elements. *@returnFormatted date */
    	protected String getDateString(a) {
    		if (suppressDate) {
    			return null;
    		} else if(dateFormat ! =null) {
    			return dateFormat.format(new Date());
    		} else {
    			return newDate().toString(); }}/** * @Method description: This method adds a custom Javadoc tag to it. * *@param javaElement
    	 * @param markAsDoNotDelete
    	 */
    	protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
    		javaElement.addJavaDocLine("*");
    		StringBuilder sb = new StringBuilder();
    		sb.append("*");
    		sb.append(MergeConstants.NEW_ELEMENT_TAG);
    		if (markAsDoNotDelete) {
    			sb.append(" do_not_delete_during_merge");
    		}
    		String s = getDateString();
    		if(s ! =null) {
    			sb.append(' '); sb.append(s); } javaElement.addJavaDocLine(sb.toString()); }}Copy the code

10.5.2 Modifying a Mapper File Name

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;

public class RenameJavaMapperPlugins extends PluginAdapter {
	private String searchString;
	private String replaceString;
	private Pattern pattern;

	public boolean validate(List<string> warnings) {

		searchString = properties.getProperty("searchString");
		replaceString = properties.getProperty("replaceString");

		booleanvalid = stringHasValue(searchString) &amp; &amp; stringHasValue(replaceString);if (valid) {
			pattern = Pattern.compile(searchString);
		} else {
			if(! stringHasValue(searchString)) { warnings.add(getString("ValidationError.18"."RenameExampleClassPlugin"."searchString"));
			}
			if(! stringHasValue(replaceString)) { warnings.add(getString("ValidationError.18"."RenameExampleClassPlugin"."replaceString")); }}return valid;
	}

	@Override
	public void initialized(IntrospectedTable introspectedTable) { String oldType = introspectedTable.getMyBatis3JavaMapperType(); Matcher matcher = pattern.matcher(oldType); oldType = matcher.replaceAll(replaceString); introspectedTable.setMyBatis3JavaMapperType(oldType); }}Copy the code

10.5.3 Custom Lombok Configuration

// Add annotations to the class
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class CustomLombokPluginAviationInfo {}// Automatically annotate the time field
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;
Copy the code
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;

public class CustomLombokPlugin extends PluginAdapter {
	private final Collection<annotations> annotations;
	/** Inherits the parent */
	private String supperClass;
	/** Filter attribute field */
	private String ignoreFields;
	/** Custom attributes - creator */
	private String author;
	/** Custom attributes - Create mailbox */
	private String email;
	/** Custom attributes - version */
	private String version;

	public CustomLombokPlugin(a) {
		annotations = newLinkedHashSet&lt; &gt; (Annotations.values().length); }@Override
	public boolean validate(List<string> warnings) {
		boolean valid = true;
		supperClass = properties.getProperty("supperClass");
		ignoreFields = properties.getProperty("ignoreFields");
		author = properties.getProperty("author"."");
		email = properties.getProperty("email"."");
		version = properties.getProperty("version"."V 1.0.1");

		try {
			Class.forName(supperClass);
		} catch (ClassNotFoundException e) {
			warnings.add(getString("ValidationError.18"."CustomLombokPlugin"."supperClass"));
		}
		return valid;
	}

	/** * get table */
	@Override
	public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	@Override
	public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	@Override
	public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addAnnotations(topLevelClass);
		return true;
	}

	/** * Set the get method (not required with Lombok, return false) */
	@Override
	public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return false;
	}

	/** * Set the set method (not required with Lombok, return false) */
	@Override
	public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return false;
	}

	/** * Set lombok annotations 

*/
private void addAnnotations(TopLevelClass topLevelClass) { for (Annotations annotation : annotations) { // Add domain import topLevelClass.addImportedType(annotation.javaType); // Add domain annotations topLevelClass.addAnnotation(annotation.asAnnotation()); } /** * Sets the parent */ if(supperClass ! =null) { FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType(supperClass); topLevelClass.addImportedType("lombok.EqualsAndHashCode"); topLevelClass.addImportedType(fullyQualifiedJavaType.getFullyQualifiedName()); topLevelClass.addAnnotation("@EqualsAndHashCode(callSuper = false)"); topLevelClass.setSuperClass(fullyQualifiedJavaType.getShortName()); } /** * filters out */ for attributes that need to be ignored List<field> fields = topLevelClass.getFields(); if (null! = ignoreFields &amp; &amp; !"".equals(ignoreFields)) { String[] field = ignoreFields.split(","); for (String ignoreField : field) { for (int i = 0; i &lt; fields.size(); i++) { Field tableField = fields.get(i); if (ignoreField.equalsIgnoreCase(tableField.getName())) { fields.remove(tableField); i--; } } } } } /** * Entity class Settings **@param properties */ @Override public void setProperties(Properties properties) { super.setProperties(properties); // @Data is default annotation annotations.add(Annotations.DATA); annotations.add(Annotations.ALL_ARGS_CONSTRUCTOR); annotations.add(Annotations.NO_ARGS_CONSTRUCTOR); annotations.add(Annotations.BUILDER); for (String annotationName : properties.stringPropertyNames()) { if (annotationName.contains(".")) { continue; } String value = properties.getProperty(annotationName); if(! Boolean.parseBoolean(value)) {// The annotation is disabled, skip it continue; } Annotations annotation = Annotations.getValueOf(annotationName); if (annotation == null) { continue; } String optionsPrefix = annotationName + "."; for (String propertyName : properties.stringPropertyNames()) { if(! propertyName.startsWith(optionsPrefix)) {// A property not related to this annotation continue; } String propertyValue = properties.getProperty(propertyName); annotation.appendOptions(propertyName, propertyValue); annotations.add(annotation); annotations.addAll(Annotations.getDependencies(annotation)); }}}/** * Mapper class set annotations and mapper file comments */ @Override public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { interfaze.addJavaDocLine("/ * *"); interfaze.addJavaDocLine("* Use today's best performance as tomorrow's latest starting point.. ~"); interfaze.addJavaDocLine("*"); interfaze.addJavaDocLine(" * Today the best performance as tomorrow newest starter!"); interfaze.addJavaDocLine("*"); interfaze.addJavaDocLine("* @ Class description: TODO(here a one-sentence description of what this class does)"); // Get table comments String tableRemarks = introspectedTable.getRemarks(); if (stringHasValue(tableRemarks)) { interfaze.addJavaDocLine("*"); interfaze.addJavaDocLine("* @ datafile comment:"); String[] remarkLines = tableRemarks.split(System.getProperty("line.separator")); for (String remarkLine : remarkLines) { interfaze.addJavaDocLine("*"+ remarkLine); }}if (stringHasValue(tableRemarks)) { interfaze.addJavaDocLine("*"); interfaze.addJavaDocLine("* @ datafile comment:"); String[] remarkLines = tableRemarks.split(System.getProperty("line.separator")); for (String remarkLine : remarkLines) { interfaze.addJavaDocLine("*" + remarkLine); } } interfaze.addJavaDocLine("*"); if(stringHasValue(email) &amp; &amp; stringHasValue(author)) { interfaze.addJavaDocLine(" * @author : <a href="\&quot; mailto:&quot;" + email "\">" + author + "</a>"); } else if(stringHasValue(author) &amp; &amp; StringUtils.isBlank(email)) { interfaze.addJavaDocLine(" * @author : " + author); } // interfaze.addJavadocline (" * @ create time: "+ getDateString())); interfaze.addJavaDocLine("* @ version:" + version); interfaze.addJavaDocLine(" * @since : " + System.getProperty("java.version")); interfaze.addJavaDocLine(" * @see <a href="\&quot; \&quot;"> "); interfaze.addJavaDocLine(" */"); interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper")); interfaze.addAnnotation("@Mapper"); return true; } /** * Entity field set */ @Override public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) { if (field.getType().getShortNameWithoutTypeArguments().equals("Date")) { field.getAnnotations().add(Annotations.DATE_TIME_FORMAT.asAnnotation()); field.getAnnotations().add(Annotations.JSON_FORMAT.asAnnotation()); topLevelClass.addImportedType(Annotations.DATE_TIME_FORMAT.javaType); topLevelClass.addImportedType(Annotations.JSON_FORMAT.javaType); } return true; } enum Annotations { DATA("data"."@Data"."lombok.Data"), BUILDER("builder"."@Builder"."lombok.Builder"), ALL_ARGS_CONSTRUCTOR("allArgsConstructor"."@AllArgsConstructor"."lombok.AllArgsConstructor"), NO_ARGS_CONSTRUCTOR("noArgsConstructor"."@NoArgsConstructor"."lombok.NoArgsConstructor"), ACCESSORS("accessors"."@Accessors"."lombok.experimental.Accessors"), TO_STRING("toString"."@ToString"."lombok.ToString"), DATE_TIME_FORMAT("dateTimeFormat"."@DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")"."org.springframework.format.annotation.DateTimeFormat"), JSON_FORMAT("jsonFormat"."@JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")"."com.fasterxml.jackson.annotation.JsonFormat"); private final String paramName; private final String name; private final FullyQualifiedJavaType javaType; private final List<string> options; Annotations(String paramName, String name, String className) { this.paramName = paramName; this.name = name; this.javaType = new FullyQualifiedJavaType(className); this.options = new ArrayList<string>(); } public static Annotations getValueOf(String paramName) { for (Annotations annotation : Annotations.values()) { if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0) { returnannotation; }}return null; } public static Collection<annotations> getDependencies(Annotations annotation) { if (annotation == ALL_ARGS_CONSTRUCTOR) { return Collections.singleton(NO_ARGS_CONSTRUCTOR); } else { returnCollections.emptyList(); }}// A trivial quoting. // Because Lombok annotation options type is almost String or boolean. private static String quote(String value) { if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value)) // case of boolean, not passed as an array. { return value; } return value.replaceAll("[\\w]+"."\" $0 \ ""); } public void appendOptions(String key, String value) { String keyPart = key.substring(key.indexOf(".") + 1); String valuePart = value.contains(",")? String.format("{%s}", value) : value; this.options.add(String.format("%s=%s", keyPart, quote(valuePart))); } public String asAnnotation(a) { if (options.isEmpty()) { return name; } StringBuilder sb = new StringBuilder(); sb.append(name); sb.append("("); boolean first = true; for (String option : options) { if (first) { first = false; } else { sb.append(","); } sb.append(option); } sb.append(")"); returnsb.toString(); }}}Copy the code

10.5.4 Custom Generation Configuration

<! -? The XML version = "1.0" encoding = "utf-8"? -->

<! GeneratorConfiguration --> generatorConfiguration
<generatorconfiguration>
	<properties resource="mybatis-generator.properties" />

	<context id="MySqlContext" targetruntime="MyBatis3">
		<property name="autoDelimitKeywords" value="true" />
		<! Code for the generated Java file -->
		<property name="javaFileEncoding" value="UTF-8" />
		<! -- Formatting 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" />
		<property name="beginningDelimiter" value="`" />
		<property name="endingDelimiter" value="`" />

		<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

		<! -- Customize lomBok plugin -->
		<plugin type="org.dllwh.template.database.mybatis.custom.CustomLombokPlugin">
			<property name="defaultSerialVersionUID" value="true" />
			<property name="supperClass" value="" />
			<property name="ignoreFields" value="" />
			<property name="author" value="${custom.property.author}" />
			<property name="email" value="${custom.property.email}" />
			<property name="version" value="V 1.0.1" />
		</plugin>
		
		<! JavaMapper file name -->
		<plugin type="org.dllwh.template.database.mybatis.custom.RenameJavaMapperPlugins">
			<property name="searchString" value="Mapper$" />
			<property name="replaceString" value="Dao" />
		</plugin>
 
		<! Comment address -->
		<commentgenerator type="org.dllwh.template.database.mybatis.custom.CustomSQLCommentGenerator">
			<property name="author" value="${custom.property.author}" />
			<property name="email" value="${custom.property.email}" />
			<property name="version" value="V 1.0.1" />
			<property name="addGetComments" value="false" />
			<property name="addSetComments" value="false" />
		</commentgenerator>

		<! -- Configure database connection -->
		<jdbcconnection driverClass="${spring.datasource.driverClassName}" connectionURL="${spring.datasource.url}" userId="${spring.datasource.username}" password="${spring.datasource.password}" />

		<! -- generated entity location -->
		<javamodelgenerator targetpackage="${model.target.package}" targetproject="src/main/java">
			<property name="trimStrings" value="true" />
		</javamodelgenerator>

		<! Create Mapper interface location -->
		<sqlmapgenerator targetpackage="${mapper.target.package}" targetproject="src/main/java">
		</sqlmapgenerator>
		
		<! Where Mapper XML is generated -->
		<javaclientgenerator type="XMLMAPPER" targetpackage="${dao.target.package}" targetproject="src/main/java">
		</javaclientgenerator>
		
		<! Set the table name and entity class name of the database
		<property name="modelOnly" value="false" /><property name="useActualColumnNames" value="false" /><columnoverride column="excep_detail" javaType="java.lang.String" jdbcType="text" /><columnoverride column="parameter" javaType="java.lang.String" jdbcType="text" /><columnoverride column="result" javaType="java.lang.String" jdbcType="text" /><table tablename="sys__operate_log" enableinsert="true" enableselectbyprimarykey="true" enableselectbyexample="false" enableupdatebyprimarykey="true" enabledeletebyprimarykey="true" enabledeletebyexample="false" enablecountbyexample="false" enableupdatebyexample="false">
			
			<! If set to true, the generated model class will use the column name instead of using the camel name method.
			
			<! -- -->
			
			
			
		</table>
	</context>
</generatorconfiguration>` ` `</annotations></string></string></field></string></annotations></string></parameter></string></string>
Copy the code