All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.trang.mybatis.generator.plugins.GuavaToStringPlugin Maven / Gradle / Ivy

The newest version!
package com.github.trang.mybatis.generator.plugins;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.Collections;
import java.util.List;
import java.util.Properties;

import static com.github.trang.mybatis.generator.plugins.Constants.SERIAL_VERSION_UID;

/**
 * 使用 Guava 的 ToStringHelper 生成 toString() 方法
 *
 * @author trang
 */
public class GuavaToStringPlugin extends PluginAdapter {

    /** 排除不需要生成 toString() 的属性 */
    private static final List NON_TO_STRING_FIELDS = Collections.singletonList(SERIAL_VERSION_UID);

    private boolean useToStringFromRoot;

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        this.useToStringFromRoot = StringUtility.isTrue(properties.getProperty("useToStringFromRoot"));
    }

    @Override
    public boolean validate(List warnings) {
        return true;
    }

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

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

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

    /**
     * 生成 toString() 方法
     */
    private void generateToString(IntrospectedTable introspectedTable, TopLevelClass topLevelClass) {
        topLevelClass.addImportedType("com.google.common.base.MoreObjects");
        // 首先创建一个 Method 对象,注意,这个 Method 是 org.mybatis.generator.api.dom.java.Method,
        // 这个 Method 是 MBG 中对对象 DOM 的一个抽象,因为我们要添加方法,所以先创建一个
        Method method = new Method();

        // 设置这个方法的可见性为 public,代码已经在一步一步构建这个方法了
        method.setVisibility(JavaVisibility.PUBLIC);

        // 设置方法的返回类型,这里注意一下的就是,returnType 是一个 FullyQualifiedJavaType
        // 这个 FullyQualifiedJavaType 是 MGB 中对 Java 中的类型的一个 DOM 封装,这个类在整个 MBG 中大量使用
        // FullyQualifiedJavaType 提供了几个静态的方法,比如 getStringInstance(),就直接返回了一个对 String 类型的封装
        method.setReturnType(FullyQualifiedJavaType.getStringInstance());

        // 设置方法的名称,至此,方法签名已经装配完成
        method.setName("toString");

        // 判断当前 MBG 运行的环境是否支持 Java5(这里就可以看出来 IntrospectedTable 类的作用了,主要是查询生成环境的作用)
        if (introspectedTable.isJava5Targeted()) {
            // 如果支持 Java5,就在方法上面生成一个 @Override 标签
            method.addAnnotation("@Override");
        }

        // 访问上下文对象(这个 context 对象是在 PluginAdapter 初始化完成后,通过 setContext 方法设置进去的,
        // 通过 getCommentGenerator 方法得到注释生成器,并调用 addGeneralMethodComment 为当前生成的方法添加注释;
        // 因为我们没有提供自己的注释生成器,所以默认的注释生成器只是说明方法是通过 MBG 生成的,对应的是哪个表而已;
        // 这句代码其实非常有意义,通过这句代码,我们基本就可能了解到 MBG 中对于方法注释的生成方式了;
        this.context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        // OK,调用 addBodyLine 开始为方法添加代码了
        // 可以看到,确实,只是简单的把要生成的代码通过 String 拼装到了 method 的 body 中而已;
        // 想到了什么?确实,我想到了 Servlet 的输出方法。MBG 默认的方法体具体的实现,就是像 Servlet 那样通过 String 输出的;
        // 所以,这才会为我们后面准备用 Velocity 来重写 MBG 提供了依据,我们只是给 MBG 添加一个 MVC 的概念;
        method.addBodyLine("return MoreObjects.toStringHelper(this).omitNullValues()");

        StringBuilder builder = new StringBuilder();
        // 通过 topLevelClass 得到当前类的所有字段,注意,这里的 Field 是 org.mybatis.generator.api.dom.java.Field
        // 这个 Field 是 MBG 对字段的一个 DOM 封装
        for (Field field : topLevelClass.getFields()) {
            // 重置 StringBuilder
            builder.setLength(0);
            // 得到字段的名称
            String fieldName = field.getName();
            // 添加字段的输出代码
            if (!NON_TO_STRING_FIELDS.contains(fieldName)) {
                builder.append("        .add(\"")
                        .append(fieldName)
                        .append("\", ")
                        .append(fieldName)
                        .append(")");
                method.addBodyLine(builder.toString());
            }
        }
        // 如果实体类有父类,则调用父类的 toString() 方法
        if ((this.useToStringFromRoot) && (topLevelClass.getSuperClass() != null)) {
            method.addBodyLine("        .add(\"super class\", super.toString())");
        }
        // 把这个字段的 toString 输出到代码中;所以才看到我们最后生成的代码结果中,每一个字段在 toString 方法中各占一行;
        method.addBodyLine("        .toString();");

        // 把拼装好的方法 DOM 添加到 topLevelClass 中,完成方法添加;
        topLevelClass.addMethod(method);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy