經常使用mybatis generator生成程式碼的你
有沒有因為生成的getter/setter而煩惱呢?
有沒有生成後又手動加toString/hashCode/Equals方法呢?
有沒有改一個欄位又要手動改寫getter/setter/toString/hashCode/Equals呢?
下面我將介紹一個mybatis generator Lombok外掛來解決以上所有問題
Lombok是一款簡單強大的程式碼工具,沒使用過Lombok外掛的同學可以用10分鐘瞭解下
1、首先定義Lombok外掛
LombokPlugin.java
package com.demo.mybatis.plugin;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
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;
import java.util.*;
/**
* A MyBatis Generator plugin to use Lombok's annotations.
* For example, use @Data annotation instead of getter ands setter.
*
* @author Paolo Predonzani (http://softwareloop.com/)
*/
public class LombokPlugin extends PluginAdapter {
private final Collection<Annotations> annotations;
/**
* LombokPlugin constructor
*/
public LombokPlugin() {
annotations = new LinkedHashSet<Annotations>(Annotations.values().length);
}
/**
* @param warnings list of warnings
* @return always true
*/
public boolean validate(List<String> warnings) {
return true;
}
/**
* Intercepts base record class generation
*
* @param topLevelClass the generated base record class
* @param introspectedTable The class containing information about the table as
* introspected from the database
* @return always true
*/
@Override
public boolean modelBaseRecordClassGenerated(
TopLevelClass topLevelClass,
IntrospectedTable introspectedTable
) {
addAnnotations(topLevelClass);
return true;
}
/**
* Intercepts primary key class generation
*
* @param topLevelClass the generated primary key class
* @param introspectedTable The class containing information about the table as
* introspected from the database
* @return always true
*/
@Override
public boolean modelPrimaryKeyClassGenerated(
TopLevelClass topLevelClass,
IntrospectedTable introspectedTable
) {
addAnnotations(topLevelClass);
return true;
}
/**
* Intercepts "record with blob" class generation
*
* @param topLevelClass the generated record with BLOBs class
* @param introspectedTable The class containing information about the table as
* introspected from the database
* @return always true
*/
@Override
public boolean modelRecordWithBLOBsClassGenerated(
TopLevelClass topLevelClass,
IntrospectedTable introspectedTable
) {
addAnnotations(topLevelClass);
return true;
}
/**
* Prevents all getters from being generated.
* See SimpleModelGenerator
*
* @param method the getter, or accessor, method generated for the specified
* column
* @param topLevelClass the partially implemented model class
* @param introspectedColumn The class containing information about the column related
* to this field as introspected from the database
* @param introspectedTable The class containing information about the table as
* introspected from the database
* @param modelClassType the type of class that the field is generated for
*/
@Override
public boolean modelGetterMethodGenerated(
Method method,
TopLevelClass topLevelClass,
IntrospectedColumn introspectedColumn,
IntrospectedTable introspectedTable,
ModelClassType modelClassType
) {
return false;
}
/**
* Prevents all setters from being generated
* See SimpleModelGenerator
*
* @param method the setter, or mutator, method generated for the specified
* column
* @param topLevelClass the partially implemented model class
* @param introspectedColumn The class containing information about the column related
* to this field as introspected from the database
* @param introspectedTable The class containing information about the table as
* introspected from the database
* @param modelClassType the type of class that the field is generated for
* @return always false
*/
@Override
public boolean modelSetterMethodGenerated(
Method method,
TopLevelClass topLevelClass,
IntrospectedColumn introspectedColumn,
IntrospectedTable introspectedTable,
ModelClassType modelClassType
) {
return false;
}
/**
* Adds the lombok annotations' imports and annotations to the class
*
* @param topLevelClass the partially implemented model class
*/
private void addAnnotations(TopLevelClass topLevelClass) {
for (Annotations annotation : annotations) {
topLevelClass.addImportedType(annotation.javaType);
topLevelClass.addAnnotation(annotation.asAnnotation());
}
}
@Override
public void setProperties(Properties properties) {
super.setProperties(properties);
//@Data is default annotation
annotations.add(Annotations.DATA);
for (String annotationName : properties.stringPropertyNames()) {
if (annotationName.contains(".")) {
// Not an annotation name
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));
}
}
}
@Override
public boolean clientGenerated(
Interface interfaze,
TopLevelClass topLevelClass,
IntrospectedTable introspectedTable
) {
interfaze.addImportedType(new FullyQualifiedJavaType(
"org.apache.ibatis.annotations.Mapper"));
interfaze.addAnnotation("@Mapper");
return true;
}
private 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");
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>();
}
private static Annotations getValueOf(String paramName) {
for (Annotations annotation : Annotations.values())
if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0)
return annotation;
return null;
}
private static Collection<Annotations> getDependencies(Annotations annotation) {
if (annotation == ALL_ARGS_CONSTRUCTOR)
return Collections.singleton(NO_ARGS_CONSTRUCTOR);
else
return Collections.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\"");
}
private 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)));
}
private String asAnnotation() {
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(")");
return sb.toString();
}
}
}
2、然後為mybatisgenerator配置外掛
<?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>
<context id="context1">
<!-- 使用自帶序列化外掛 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- 使用自定義的外掛 -->
<plugin type="com.demo.mybatis.plugin.LombokPlugin"/>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8"
userId="root" password="123456">
</jdbcConnection>
<javaModelGenerator targetPackage="com.ilovey.biz.entity.base"
targetProject="ilovey.biz/src/main/java"/>
<sqlMapGenerator targetPackage="com.ilovey.biz.mapper.base"
targetProject="ilovey.biz/src/main/resources"/>
<javaClientGenerator targetPackage="com.ilovey.biz.mapper.base"
targetProject="ilovey.biz/src/main/java" type="XMLMAPPER"/>
<table tableName="us_user_info" domainObjectName="UsUserInfo">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
3、生成效果
package com.demo.biz.entity.base;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
@Data
public class UsUserInfo implements Serializable {
/**
*
*/
private Integer id;
/**
* 使用者id
*/
private Integer userId;
/**
* 暱稱
*/
private String nickName;
/**
* 頭像
*/
private String headImage;
/**
* 手機號碼
*/
private String mobile;
/**
* 性別(0保密,1男,2女)
*/
private Integer sex;
/**
* 地區
*/
private Integer region;
/**
* 個性簽名
*/
private String signature;
/**
* 使用者型別(1普通使用者,2達人使用者)
*/
private Byte type;
/**
* 使用者種類
*/
private String kindCode;
/**
* r熱度
*/
private Integer hot;
/**
* 建立時間
*/
private Date createTime;
/**
* 更新時間
*/
private Date updateTime;
private static final long serialVersionUID = 1L;
}
本文所有程式碼及demo:https://gitee.com/chaocloud/generator-demo.git