后端代码生成工具SDP系列二(替代Mybatis generator plugin的简单练习)

  • 启动SDP
  • 了解基本功能
  • 熟悉页面一:工作区
  • 熟悉页面二:工作区配置项
  • 熟悉页面三:项目(或子组件)
  • 熟悉页面四:模板
  • 熟悉页面五:select语句、接口定义等
  • 第一个例子(与Mybatis generator plugin没有本质的差别)
  • 准备好测试用的工作区(通过导入、导出,sdp_workspace页面)
  • 重新配置工作区连接的数据库(sdp_workspace页面)
  • 删除导入的自定义接口配置(sdp_sql页面)
  • 设置需要生成文件的表(sdp_project页面)
  • 设置代码生成目录(sdp_project页面)
  • 生成代码


启动SDP

下载源代码,或已经打包好的工具后,双击startup_db_in_home.bat(Windows)或执行java -jar sdp-1.8.0.jar(Linux、Mac),启动工具。启动后的控制台会输出如下信息:

python 实现类似 mybatis plus 替代mybatis_java

启动服务后,程序会自动在浏览器中打开地址http://localhost:9882(Windows或Mac),或按照提示,手动通过浏览器打开http://localhost:9882,就可以看到管理页面了。缺省的页面下图所示:

python 实现类似 mybatis plus 替代mybatis_数据库_02

SDP工具包含了SDP工程本身的配置及模板。采用的是标准的SpringBoot Controller-Service-Dao架构。

了解基本功能

SDP主要包含了5个页面,分别是:工作区;工作区配置项;项目(或子组件);模板;select语句及接口定义。
这5个内容之间的关系如下:






工作区

工作区配置项

项目或子组件

select语句及接口定义

模板


熟悉页面一:工作区

工作区必须有一个名称,一个工作区只能对应到一个数据库连接。工作区中主要配置了数据库连接的属性。工作区支持导出、导入,为了安全起见,在导出时,数据库密码是不会被导出的。

导入工作区时可以换名,这样通过导出+导入且换名,就可以复制一个工作区的所有文件到另外一个工作区。

python 实现类似 mybatis plus 替代mybatis_工作区_03

熟悉页面二:工作区配置项

工作区配置项除了定义作者、版本外,还定义了代码中使用的包名。可以通过批量替换值的方式,根据自己项目的需要替换为自己项目的包名。

python 实现类似 mybatis plus 替代mybatis_工作区_04

熟悉页面三:项目(或子组件)

通过项目将个产品的所有代码进行了拆分,典型的例子包括了api、controller、service、dao这几个部分。其中controller用于提供接口,api定义了controller接口参数、返回值,service用于实现具体业务逻辑,dao用于与数据库打交道。每个部分可能会分属于不同的源代码目录,也可能在同一个目录,仅仅做逻辑上的区分。

SDP工具本身使用了4个逻辑上独立的4个组件,他们都在同一个根目录,然后通过模板中的包名来控制输出目录。

自动生成哪些数据库表对应的源代码就是在这里控制,修改对应项目的表,然后点击生成文件,就可以在对应的目录下根据数据库表生成对应的源代码了。多个表用逗号分隔,如果代码的类名和数据库表不一致,可以用table_name as alias_table_name的格式进行换名,例如sys_role as role或sys_role as my_roles。注意:无论是表明还是换名都必须符合小写英文加下划线的规则。

python 实现类似 mybatis plus 替代mybatis_mybatis_05

熟悉页面四:模板

模板就是一个项目的“母鸡”,通过项目中配置的表,工具会自动在对应的目录下生成源代码(“鸡蛋”)。

模板包括基本属性和模板内容。SDP工具提供了一个编辑器,专门用于编辑模板。在编辑模板时提供了几个高级功能:

语法提示:在输入{,{*,&这3种起始符号后,按Control键,工具会提示合法的后续关键字。

python 实现类似 mybatis plus 替代mybatis_数据库_06

熟悉页面五:select语句、接口定义等

这块功能是SDP工具的灵魂,通过配置select语句、配置接口等,实现了专注于编写实际业务逻辑的目的。

python 实现类似 mybatis plus 替代mybatis_数据库_07

第一个例子(与Mybatis generator plugin没有本质的差别)

例如我们有一个mysql数据库,数据库名称为sdp,其中有一个表,表名为test_workspace:

CREATE TABLE test_workspace (
  id int(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(200) NOT NULL,
  root_path VARCHAR(100) DEFAULT NULL,
  db_host VARCHAR(100) DEFAULT NULL,
  db_port INT DEFAULT NULL,
  db_database VARCHAR(200) DEFAULT NULL,
  db_username VARCHAR(45) DEFAULT NULL,
  db_password VARCHAR(200) DEFAULT NULL,
  db_classname VARCHAR(200) DEFAULT NULL,
  db_jdbcurl VARCHAR(500),
  remark VARCHAR(200) DEFAULT NULL,
  extra_info TEXT,
  PRIMARY KEY (id),
  UNIQUE KEY unique_test_workspace (name)
);

准备好测试用的工作区(通过导入、导出,sdp_workspace页面)

我们先配置好工作区(sdp_workspace页面),可以先将缺省的sdp工作区导出,然后再次导入,并将工作区名称设置为test,操作过程和最后的结果页面如下图:

python 实现类似 mybatis plus 替代mybatis_mybatis_08


python 实现类似 mybatis plus 替代mybatis_配置项_09


python 实现类似 mybatis plus 替代mybatis_数据库_10


python 实现类似 mybatis plus 替代mybatis_工作区_11


python 实现类似 mybatis plus 替代mybatis_java_12


python 实现类似 mybatis plus 替代mybatis_数据库_13


python 实现类似 mybatis plus 替代mybatis_数据库_14


python 实现类似 mybatis plus 替代mybatis_工作区_15

重新配置工作区连接的数据库(sdp_workspace页面)

导入工作区后,需要先配置工作区连接的数据库。刚刚导入的工作区使用的是H2数据库,我们需要将其修改为测试使用的mysql数据库。

python 实现类似 mybatis plus 替代mybatis_数据库_16


python 实现类似 mybatis plus 替代mybatis_mybatis_17

删除导入的自定义接口配置(sdp_sql页面)

导入的工作区会保留其他工作区设置的select语句等,这些配置需要根据自己项目的需要重新设置,所以需要全部删除。

python 实现类似 mybatis plus 替代mybatis_工作区_18

设置需要生成文件的表(sdp_project页面)

一个数据库中会有很多表,不是每个表都需要生成Control、Service、Dao文件,所以就需要进行配置。之前导入的工作区,是按照SDP工具本身的需求,设置了若干数据表,我们需要根据自己的需要设置生成哪些数据表的文件。

python 实现类似 mybatis plus 替代mybatis_数据库_19


python 实现类似 mybatis plus 替代mybatis_配置项_20


python 实现类似 mybatis plus 替代mybatis_数据库_21


配置好以后的页面如下:

python 实现类似 mybatis plus 替代mybatis_配置项_22

设置代码生成目录(sdp_project页面)

导入的工作区会隐藏代码主目录,以避免在不同用户之间传递导出文件导致目录不一致的问题。在生成文件之前需要先设置代码所在目录。

python 实现类似 mybatis plus 替代mybatis_mybatis_23


python 实现类似 mybatis plus 替代mybatis_mybatis_24


python 实现类似 mybatis plus 替代mybatis_配置项_25


python 实现类似 mybatis plus 替代mybatis_数据库_26


python 实现类似 mybatis plus 替代mybatis_java_27


python 实现类似 mybatis plus 替代mybatis_java_28

生成代码

选中一个工程的任何一行,然后点击生成。就可以生成代码了。生成后的代码结果如下图:

python 实现类似 mybatis plus 替代mybatis_java_29


需要注意,其中domain目录有一个Criterion.java文件,这个文件在mybatis generator plugin中是在每个Example类中定义的静态类。SDP工具将这个静态类提取出来,一个是为了减少Example类的行数,另外一个目的是可以用通用的方式动态修改每个Example类的查询条件。

Criterion.java的内容如下:

package cn.mysdp.biz.domain;

import java.util.List;

public class Criterion {
    private String condition;

    private Object value;

    private Object secondValue;

    private boolean noValue;

    private boolean singleValue;

    private boolean betweenValue;

    private boolean listValue;

    private String typeHandler;

    public String getCondition() {
        return condition;
    }

    public Object getValue() {
        return value;
    }

    public Object getSecondValue() {
        return secondValue;
    }

    public boolean isNoValue() {
        return noValue;
    }

    public boolean isSingleValue() {
        return singleValue;
    }

    public boolean isBetweenValue() {
        return betweenValue;
    }

    public boolean isListValue() {
        return listValue;
    }

    public String getTypeHandler() {
        return typeHandler;
    }

    public Criterion(String condition) {
        super();
        this.condition = condition;
        this.typeHandler = null;
        this.noValue = true;
    }

    public Criterion(String condition, Object value, String typeHandler) {
        super();
        this.condition = condition;
        this.value = value;
        this.typeHandler = typeHandler;
        if (value instanceof List<?>) {
            this.listValue = true;
        } else {
            this.singleValue = true;
        }
    }

    public Criterion(String condition, Object value) {
        this(condition, value, null);
    }

    public Criterion(String condition, Object value, Object secondValue, String typeHandler) {
        super();
        this.condition = condition;
        this.value = value;
        this.secondValue = secondValue;
        this.typeHandler = typeHandler;
        this.betweenValue = true;
    }

    public Criterion(String condition, Object value, Object secondValue) {
        this(condition, value, secondValue, null);
    }
}