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 similar com/myproject/generatorConfig.properties The 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:
- If accuracy >0 or length >18, java.math.bigDecimal is used
- If precision =0 and 10<= length <=18, java.lang.long is used
- If precision =0 and 5<= length <=9, java.lang.INTEGER is used
- 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 oncatalog andschema To generate subpackages.if false I’ll just use ittargetPackage Properties. |
immutable | false | This property is used to configure whether the entity class attribute is mutable. If set to true , the constructor will be used and will not be generatedsetter Methods.If it is false , entity class attributes can be changed. |
trimStrings | false | Whether to perform database query resultstrim operation |
<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 -> 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:
-
In the project to create entity class CustomSQLCommentGenerator DefaultCommentGenerato inheritance
-
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
-
The main class MyBatis -generator is run again, and the class and field annotations are successfully generated
-
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 & & 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 > 1) { // Where the comment begins field.addJavaDocLine("/ * *"); for (int i = 0; i < 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) & & stringHasValue(author)) { topLevelClass.addJavaDocLine(" * @author : <a href="\" mailto:"" + email "\">" + author + "</a>"); } else if(stringHasValue(author) & & ! stringHasValue(email)) { topLevelClass.addJavaDocLine(" * @author : " + author); } else if(stringHasValue(email) & & ! 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="\" \""> "); 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 -> method.addJavaDocLine(" * @param " + parameter.getName())); method.addJavaDocLine("*"); // If there is a return type, add @return String returnType = "void"; if(method.getReturnType() ! =null& & ! 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) & & 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< > (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 & & !"".equals(ignoreFields)) {
String[] field = ignoreFields.split(",");
for (String ignoreField : field) {
for (int i = 0; i < 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) & & stringHasValue(author)) { interfaze.addJavaDocLine(" * @author : <a href="\" mailto:"" + email "\">" + author + "</a>");
} else if(stringHasValue(author) & & 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="\" \""> ");
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