后端代码生成工具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),启动工具。启动后的控制台会输出如下信息:
启动服务后,程序会自动在浏览器中打开地址http://localhost:9882(Windows或Mac),或按照提示,手动通过浏览器打开http://localhost:9882,就可以看到管理页面了。缺省的页面下图所示:
SDP工具包含了SDP工程本身的配置及模板。采用的是标准的SpringBoot Controller-Service-Dao架构。
了解基本功能
SDP主要包含了5个页面,分别是:工作区;工作区配置项;项目(或子组件);模板;select语句及接口定义。
这5个内容之间的关系如下:
工作区
工作区配置项
项目或子组件
select语句及接口定义
模板
熟悉页面一:工作区
工作区必须有一个名称,一个工作区只能对应到一个数据库连接。工作区中主要配置了数据库连接的属性。工作区支持导出、导入,为了安全起见,在导出时,数据库密码是不会被导出的。
导入工作区时可以换名,这样通过导出+导入且换名,就可以复制一个工作区的所有文件到另外一个工作区。
熟悉页面二:工作区配置项
工作区配置项除了定义作者、版本外,还定义了代码中使用的包名。可以通过批量替换值的方式,根据自己项目的需要替换为自己项目的包名。
熟悉页面三:项目(或子组件)
通过项目将个产品的所有代码进行了拆分,典型的例子包括了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。注意:无论是表明还是换名都必须符合小写英文加下划线的规则。
熟悉页面四:模板
模板就是一个项目的“母鸡”,通过项目中配置的表,工具会自动在对应的目录下生成源代码(“鸡蛋”)。
模板包括基本属性和模板内容。SDP工具提供了一个编辑器,专门用于编辑模板。在编辑模板时提供了几个高级功能:
语法提示:在输入{,{*,&这3种起始符号后,按Control键,工具会提示合法的后续关键字。
熟悉页面五:select语句、接口定义等
这块功能是SDP工具的灵魂,通过配置select语句、配置接口等,实现了专注于编写实际业务逻辑的目的。
第一个例子(与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,操作过程和最后的结果页面如下图:
重新配置工作区连接的数据库(sdp_workspace页面)
导入工作区后,需要先配置工作区连接的数据库。刚刚导入的工作区使用的是H2数据库,我们需要将其修改为测试使用的mysql数据库。
删除导入的自定义接口配置(sdp_sql页面)
导入的工作区会保留其他工作区设置的select语句等,这些配置需要根据自己项目的需要重新设置,所以需要全部删除。
设置需要生成文件的表(sdp_project页面)
一个数据库中会有很多表,不是每个表都需要生成Control、Service、Dao文件,所以就需要进行配置。之前导入的工作区,是按照SDP工具本身的需求,设置了若干数据表,我们需要根据自己的需要设置生成哪些数据表的文件。
配置好以后的页面如下:
设置代码生成目录(sdp_project页面)
导入的工作区会隐藏代码主目录,以避免在不同用户之间传递导出文件导致目录不一致的问题。在生成文件之前需要先设置代码所在目录。
生成代码
选中一个工程的任何一行,然后点击生成。就可以生成代码了。生成后的代码结果如下图:
需要注意,其中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);
}
}