Mybatis Generator是供开发者在mybatis开发时,快速构建mapper xml,mapper类,model类的一个插件工具。它相对来说对开发者是有很大的帮助的,但是它也有不足之处,比如生成的xml配置文件不是完全可以拿来使用的,有很多时候需要开发者自行修改后才可以使用。因为它还是值得学习并使用的,因此有了本文的总结。
环境说明:
springboot2.0.2,
mybatis-generator-plugin版本1.3.2,
mysql-5.7.24-winx64
Maven依赖导入:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
。。。
这段maven配置内容的作用是用来导入mybatis-generator插件的,同时需要指定插件版本,以及mybatis generator生成配置文件路径。configuration->overwrite属性用来指定是否覆盖本地已有文件。
数据表构建:
为了配置mybatis插件生成对应mapper相关文件,我们需要定义一下数据表:jobitem。
-- ----------------------------
-- Table structure for `jobitem`
-- ----------------------------
DROP TABLE IF EXISTS `jobitem`;
CREATE TABLE `jobitem` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '唯一键 pk',
`appId` varchar(32) NOT NULL COMMENT 'yarn任务id(applicationId)',
`submitFilePath` varchar(256) NOT NULL COMMENT '提交脚本路径',
`state` varchar(16) DEFAULT NULL COMMENT '任务状态',
`monitorType` varchar(512) DEFAULT NULL COMMENT '监控列表',
`createUserId` varchar(32) NOT NULL COMMENT '创建者关联Id',
`createUserName` varchar(32) NOT NULL COMMENT '创建者用户名',
`createTime` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `key` (`appId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='yarn任务持久化存储对象'; -- ----------------------------
-- Records of jobitem
-- ----------------------------
这里的数据表是mysql下的表,在mysql下导入并生成jobitem表。
配置Mybatis配置文件(/src/main/resources/generator/generatorConfig.xml):
项目结构如下:
generatorConfig.xml配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration>
<!-- 数据库驱动包位置 -->
<classPathEntry
location="D:\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar" />
<context id="Mysql" targetRuntime="MyBatis3Simple"
defaultModelType="flat">
<!-- ( property*,plugin*, commentGenerator?, jdbcConnection, javaTypeResolver?,
javaModelGenerator, sqlMapGenerator?, javaClientGenerator?, table+ ) --> <property name="beginningDelimiter" value="`" />
<property name="endingDelimiter" value="`" /> <!-- 生成的 Java 文件的编码 -->
<property name="javaFileEncoding" value="UTF-8" />
<!-- 格式化 Java 代码 -->
<property name="javaFormatter"
value="org.mybatis.generator.api.dom.DefaultJavaFormatter" />
<!-- 格式化 XML 代码 -->
<property name="xmlFormatter"
value="org.mybatis.generator.api.dom.DefaultXmlFormatter" /> <!-- 自定义注释生成器 -->
<commentGenerator>
</commentGenerator> <!--<plugin type="tk.mybatis.mapper.generator.MapperPlugin"> <property
name="mappers" value="com.ad.core.mapper"/> </plugin> --> <!-- 连接 那个知道把参数改为 ${}的形式,并且用的yml的 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mydb" userId="root"
password="123456">
</jdbcConnection> <!--生成Model类存放位置 -->
<javaModelGenerator targetPackage="com.dx.jobmonitor.model"
targetProject="E:/work/git/...-model/src/main/java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator> <!--生成mapper.xml配置文件位置 -->
<sqlMapGenerator targetPackage="mapper"
targetProject="E:/work/git/f...-mapper/src/main/resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator> <!-- 生成mapper接口文件位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.dx.jobmonitor.mapper"
targetProject="E:/work/git/feature-26692/。。。-mapper/src/main/java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator> <!--
(已经自定义修改了某些sql语句,因此如果重新生成导致sql被覆盖)需要生成的实体类对应的表名,多个实体类复制多份该配置即可
-->
<table tableName="sjmc_jobitem" enableCountByExample="false"
enableDeleteByExample="false" enableDeleteByPrimaryKey="false"
enableInsert="true" enableSelectByExample="true"
enableUpdateByExample="true" enableUpdateByPrimaryKey="true">
<generatedKey column="id" sqlStatement="Mysql"
identity="true" />
</table>
</context>
</generatorConfiguration>
运行mybatis generator插件,生成mapper类/mapper.xml/model类:
到此为止,所有的配置已完毕,如果在ecplise中使用,则右击工程-》maven build...-》global添加命令mybatis-generator:generate-》运行,代码生成完毕!
自定义字段/getter/settetr注释
按照上边配置完成后,会发现生成的model类,没有数据注释信息。希望将数据库的备注自动生成到model属性字段,以及setter/getter方法上。实际上这个想法是可行的,我们需要自定义commentGenerator。
第一步:新建一个插件项目
这里必须这么做,否则后边会出现错误:自定义注释类无法初始化错误。
第二步:插件项目引入maven依赖
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
第三步:添加自定义注释插件类:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties; import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.InnerEnum;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.config.PropertyRegistry; /**
* 自定义实现 注释生成器 CommentGenerator 接口
*/
public class MyCommentGenerator implements CommentGenerator {
private Properties properties;
private Properties systemPro;
private boolean suppressDate;
private boolean suppressAllComments;
private String nowTime; public MyCommentGenerator() {
super();
properties = new Properties();
systemPro = System.getProperties();
suppressDate = false;
suppressAllComments = false;
nowTime = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date());
} public void addJavaFileComment(CompilationUnit compilationUnit) {
if (suppressAllComments) {
return;
}
return;
} /**
* Adds a suitable comment to warn users that the element was generated, and
* when it was generated.
*/
public void addComment(XmlElement xmlElement) {
return;
} public void addRootComment(XmlElement rootElement) {
// add no document level comments by default
return;
} public void addConfigurationProperties(Properties properties) {
this.properties.putAll(properties);
suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
} /**
* 判断传入参数是否为true
* @param property
* @return
*/
private boolean isTrue(String property) {
if("true".equals(property)){
return true;
}
return false;
} /**
* This method adds the custom javadoc tag for. You may do nothing if you do
* not wish to include the Javadoc tag - however, if you do not include the
* Javadoc tag then the Java merge capability of the eclipse plugin will
* break.
*
* @param javaElement
* the java element
*/
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());
} /**
* This method returns a formated date string to include in the Javadoc tag
* and XML comments. You may return null if you do not want the date in
* these documentation elements.
*
* @return a string representing the current timestamp, or null
*/
protected String getDateString() {
String result = null;
if (!suppressDate) {
result = nowTime;
}
return result;
} public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
innerClass.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
sb.append(" ");
sb.append(getDateString());
innerClass.addJavaDocLine(sb.toString().replace("\n", " "));
innerClass.addJavaDocLine(" */");
} public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
innerEnum.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
innerEnum.addJavaDocLine(sb.toString().replace("\n", " "));
innerEnum.addJavaDocLine(" */");
} /**
* 设置字段注释
*/
public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
field.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
sb.append("<br> \n");
sb.append(" * 列名:" + introspectedColumn.getActualColumnName() + " 类型:" + introspectedColumn.getJdbcTypeName()
+ "(" + introspectedColumn.getLength() + ")" + " 允许空:" + introspectedColumn.isNullable() + " 缺省值:"
+ introspectedColumn.getDefaultValue());
field.addJavaDocLine(sb.toString());
field.addJavaDocLine(" */");
} public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
field.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
field.addJavaDocLine(sb.toString().replace("\n", " "));
field.addJavaDocLine(" */");
} public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
method.addJavaDocLine("/**");
addJavadocTag(method, false);
method.addJavaDocLine(" */");
} /**
* 设置getter方法注释
*/
public void addGetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
method.addJavaDocLine("/**");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0); //加入系统用户
sb.append(" * @author ");
sb.append(systemPro.getProperty("user.name"));
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0); //是否加入时间戳
if(suppressDate){
sb.append(" * @date " + nowTime);
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0);
} sb.append(" * @return ");
sb.append(introspectedColumn.getActualColumnName());
sb.append(" ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n", " "));
method.addJavaDocLine(" */");
} /**
* 设置setter方法注释
*/
public void addSetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
method.addJavaDocLine("/**");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0); //加入系统用户
sb.append(" * @author ");
sb.append(systemPro.getProperty("user.name"));
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0); //是否加入时间戳
if(suppressDate){
sb.append(" * @date " + nowTime);
method.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0);
} Parameter parm = method.getParameters().get(0);
sb.append(" * @param ");
sb.append(parm.getName());
sb.append(" ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n", " "));
method.addJavaDocLine(" */");
} public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
innerClass.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
innerClass.addJavaDocLine(sb.toString().replace("\n", " "));
sb.setLength(0);
sb.append(" * @author ");
sb.append(systemPro.getProperty("user.name"));
sb.append(" ");
sb.append(nowTime);
innerClass.addJavaDocLine(" */");
} }
第四步:修改*-web项目pom中mybatis-generator-plugin配置信息,导入自定义注释插件的依赖。
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>com.dx.jobmonitor.plugins.mybatis</groupId>
<artifactId>...-plugins-mybatis</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>E:/work/git/。。。-plugins-mybatis/target/...-plugins-mybatis-1.0.0-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
</plugin>
。。。
第五步:修改generatorConfig.xml配置文件给引入自定义注释类
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration>
<!-- 数据库驱动包位置 -->
<classPathEntry
location="D:\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar" />
<context id="Mysql" targetRuntime="MyBatis3Simple"
defaultModelType="flat">
。。。
<!-- 自定义注释生成器 -->
<commentGenerator
type="com.boco.jobmonitor.plugins.mybatis.MyCommentGenerator">
</commentGenerator>
。。。
第六步:重新运行mybatis-generator插件,生成mapper xml,mapper类,model类。
此时model类如下:
import java.util.Date; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id; public class Jobitem {
/**
* 唯一键 pk<br>
* 列名:id 类型:INTEGER(10) 允许空:false 缺省值:null
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; /**
* yarn任务id(applicationId)<br>
* 列名:appId 类型:VARCHAR(32) 允许空:false 缺省值:null
*/
private String appid; /**
* 提交脚本路径<br>
* 列名:submitFilePath 类型:VARCHAR(256) 允许空:false 缺省值:null
*/
private String submitfilepath; /**
* 任务状态<br>
* 列名:state 类型:VARCHAR(16) 允许空:true 缺省值:null
*/
private String state; /**
* 监控列表<br>
* 列名:monitorType 类型:VARCHAR(512) 允许空:true 缺省值:null
*/
private String monitortype; /**
* 创建者关联Id<br>
* 列名:createUserId 类型:VARCHAR(32) 允许空:false 缺省值:null
*/
private String createuserid; /**
* 创建者用户名<br>
* 列名:createUserName 类型:VARCHAR(32) 允许空:false 缺省值:null
*/
private String createusername; /**
* 创建时间<br>
* 列名:createTime 类型:TIMESTAMP(19) 允许空:false 缺省值:null
*/
private Date createtime; /**
* 唯一键 pk
*
* @return id 唯一键 pk
*/
public Long getId() {
return id;
} /**
* 唯一键 pk
*
* @param id
* 唯一键 pk
*/
public void setId(Long id) {
this.id = id;
} /**
* yarn任务id(applicationId)
*
* @return appId yarn任务id(applicationId)
*/
public String getAppid() {
return appid;
} /**
* yarn任务id(applicationId)
*
* @param appid
* yarn任务id(applicationId)
*/
public void setAppid(String appid) {
this.appid = appid == null ? null : appid.trim();
} /**
* 提交脚本路径
*
* @return submitFilePath 提交脚本路径
*/
public String getSubmitfilepath() {
return submitfilepath;
} /**
* 提交脚本路径
*
* @param submitfilepath
* 提交脚本路径
*/
public void setSubmitfilepath(String submitfilepath) {
this.submitfilepath = submitfilepath == null ? null : submitfilepath.trim();
} /**
* 任务状态
*
* @return state 任务状态
*/
public String getState() {
return state;
} /**
* 任务状态
*
* @param state
* 任务状态
*/
public void setState(String state) {
this.state = state == null ? null : state.trim();
} /**
* 监控列表
*
* @return monitorType 监控列表
*/
public String getMonitortype() {
return monitortype;
} /**
* 监控列表
*
* @param monitortype
* 监控列表
*/
public void setMonitortype(String monitortype) {
this.monitortype = monitortype == null ? null : monitortype.trim();
} /**
* 创建者关联Id
*
* @return createUserId 创建者关联Id
*/
public String getCreateuserid() {
return createuserid;
} /**
* 创建者关联Id
*
* @param createuserid
* 创建者关联Id
*/
public void setCreateuserid(String createuserid) {
this.createuserid = createuserid == null ? null : createuserid.trim();
} /**
* 创建者用户名
*
* @return createUserName 创建者用户名
*/
public String getCreateusername() {
return createusername;
} /**
* 创建者用户名
*
* @param createusername
* 创建者用户名
*/
public void setCreateusername(String createusername) {
this.createusername = createusername == null ? null : createusername.trim();
} /**
* 创建时间
*
* @return createTime 创建时间
*/
public Date getCreatetime() {
return createtime;
} /**
* 创建时间
*
* @param createtime
* 创建时间
*/
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
}
参考:
mybatis插件--(1)--mybatis generator自定义插件或者扩展报Cannot instantiate object of type XXX
https://blog.csdn.net/u_ascend/article/details/80742919
mybatis generator为实体类生成自定义注释(读取数据库字段的注释添加到实体类,不修改源码)
https://blog.csdn.net/u012045045/article/details/83012681
使用mybatis-generator添加自定义插件时提示无法实例化插件类 Cannot instantiate object of type
https://blog.csdn.net/twj13162380953/article/details/81286714
Mybatis-generator自动生成代码时候提取数据库的字段注释作为实体类字段、getter/setter方法的注释
https://www.jianshu.com/p/7d58982a5b0b
mybatis-generator自动生成代码插件使用详解
https://www.cnblogs.com/handsomeye/p/6268513.html