# linitly-generator **Repository Path**: linitly/linitly-generator ## Basic Information - **Project Name**: linitly-generator - **Description**: 基于mybatis-generator,修改生成适用日常开发的通用开发文件;服务于linitly-boot项目; - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2020-11-17 - **Last Updated**: 2022-05-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: mybatis-generator, 自动生成, Java ## README ## linitly-generator 本项目是基于`mybatis-generator 1.4.0`版本进行修改,为生成适用于项目的相关文件,可以为后端生成一套基本CRUD文件,避免简单的重复工作。 环境要求:JDK1.8+ **重要**:本项目以`linitly-boot`为脚手架,生成文件内部分基础信息**以此脚手架为基础**,但不完全依赖于此脚手架;主要为该脚手架定制; Gitee地址:https://gitee.com/linitly/linitly-boot.git 开发人员可修改生成后的文件,也可以修改源码来适用于自身项目。 ### 效果演示 #### xml配置 ```xml ``` #### 数据库表ddl ```sql CREATE TABLE `test_generator` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `test_aa` VARCHAR(16) NOT NULL DEFAULT '' COMMENT 'aaaaa', `test_bb` VARCHAR(100) DEFAULT '' COMMENT 'bbbbb', `test_cc` INT DEFAULT 0 COMMENT 'ccccc', `test_dd` bigint NOT NULL DEFAULT 0 COMMENT 'ddddd', `test_ee` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'eeeee', `test_ff` text COMMENT 'ffffff', `test_gg` DOUBLE(5, 2) NOT NULL DEFAULT 0 COMMENT 'gggggg', `enabled` int(1) NOT NULL DEFAULT 1 COMMENT '启用状态(1:启用(默认);0:禁用;)', `created_user_id` bigint NOT NULL DEFAULT 0 COMMENT '创建人id', `created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `last_modified_user_id` bigint NOT NULL DEFAULT 0 COMMENT '最后修改人id', `last_modified_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次更新时间', PRIMARY KEY (id) ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '测试生成' ROW_FORMAT = Dynamic; ``` #### mapper文件 ```xml id, test_aa, test_bb, test_cc, test_dd, test_ee, test_ff, test_gg, enabled, created_user_id, created_time, last_modified_user_id, last_modified_time DELETE FROM test_generator WHERE id = #{id, jdbcType=BIGINT} INSERT INTO test_generator (id, test_aa, test_bb, test_cc, test_dd, test_ee, test_ff, test_gg, created_user_id, last_modified_user_id) VALUES (#{id, jdbcType=BIGINT}, #{testAa, jdbcType=VARCHAR}, #{testBb, jdbcType=VARCHAR}, #{testCc, jdbcType=INTEGER}, #{testDd, jdbcType=BIGINT}, #{testEe, jdbcType=TIMESTAMP}, #{testFf, jdbcType=LONGVARCHAR}, #{testGg, jdbcType=DOUBLE}, #{createdUserId, jdbcType=BIGINT}, #{lastModifiedUserId, jdbcType=BIGINT}) UPDATE test_generator SET test_aa = #{testAa, jdbcType=VARCHAR}, test_bb = #{testBb, jdbcType=VARCHAR}, test_cc = #{testCc, jdbcType=INTEGER}, test_dd = #{testDd, jdbcType=BIGINT}, test_ee = #{testEe, jdbcType=TIMESTAMP}, test_ff = #{testFf, jdbcType=LONGVARCHAR}, test_gg = #{testGg, jdbcType=DOUBLE}, last_modified_user_id = #{lastModifiedUserId, jdbcType=BIGINT} WHERE id = #{id, jdbcType=BIGINT} INSERT INTO test_generator id, test_aa, test_bb, test_cc, test_dd, test_ee, test_ff, test_gg, created_user_id, last_modified_user_id, #{id, jdbcType=BIGINT}, #{testAa, jdbcType=VARCHAR}, #{testBb, jdbcType=VARCHAR}, #{testCc, jdbcType=INTEGER}, #{testDd, jdbcType=BIGINT}, #{testEe, jdbcType=TIMESTAMP}, #{testFf, jdbcType=LONGVARCHAR}, #{testGg, jdbcType=DOUBLE}, #{createdUserId, jdbcType=BIGINT}, #{lastModifiedUserId, jdbcType=BIGINT}, UPDATE test_generator test_aa = #{testAa, jdbcType=VARCHAR}, test_bb = #{testBb, jdbcType=VARCHAR}, test_cc = #{testCc, jdbcType=INTEGER}, test_dd = #{testDd, jdbcType=BIGINT}, test_ee = #{testEe, jdbcType=TIMESTAMP}, test_ff = #{testFf, jdbcType=LONGVARCHAR}, test_gg = #{testGg, jdbcType=DOUBLE}, last_modified_user_id = #{lastModifiedUserId, jdbcType=BIGINT}, where id = #{id, jdbcType=BIGINT} ``` #### dao层文件 ```java package org.linitly.business.dao; import java.util.List; import org.linitly.base.annotation.DeleteBackup; import org.linitly.business.entity.TestGenerator; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ public interface TestGeneratorMapper { @DeleteBackup int deleteById(Long id); int insert(TestGenerator testGenerator); TestGenerator findById(Long id); int updateById(TestGenerator testGenerator); List findAll(TestGenerator testGenerator); int insertSelective(TestGenerator testGenerator); int updateByIdSelective(TestGenerator testGenerator); } ``` #### service文件 ```java package org.linitly.business.service; import java.util.List; import org.linitly.business.dao.TestGeneratorMapper; import org.linitly.business.dto.TestGeneratorDTO; import org.linitly.business.entity.TestGenerator; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ @Service public class TestGeneratorService { @Autowired private TestGeneratorMapper testGeneratorMapper; public void insert(TestGeneratorDTO dto) { TestGenerator testGenerator = new TestGenerator(); BeanUtils.copyProperties(dto, testGenerator); testGeneratorMapper.insertSelective(testGenerator); } public void updateById(TestGeneratorDTO dto) { TestGenerator testGenerator = new TestGenerator(); BeanUtils.copyProperties(dto, testGenerator); testGeneratorMapper.updateByIdSelective(testGenerator); } public TestGenerator findById(Long id) { return testGeneratorMapper.findById(id); } public List findAll(TestGenerator testGenerator) { return testGeneratorMapper.findAll(testGenerator); } public void deleteById(Long id) { testGeneratorMapper.deleteById(id); } } ``` #### controller文件 ```java package org.linitly.business.controller; import com.github.pagehelper.PageHelper; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import java.util.List; import org.linitly.base.annotation.Pagination; import org.linitly.base.annotation.Result; import org.linitly.base.constant.admin.AdminCommonConstant; import org.linitly.base.helper.groups.InsertValidGroup; import org.linitly.base.helper.groups.UpdateValidGroup; import org.linitly.business.dto.TestGeneratorDTO; import org.linitly.business.entity.TestGenerator; import org.linitly.business.service.TestGeneratorService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ @Result @RestController @RequestMapping("/testGenerator") @Api(tags = "测试生成管理") public class TestGeneratorController { @Autowired private TestGeneratorService testGeneratorService; @PostMapping("/insert") @ApiOperation(value = "添加测试生成") public void insert(@RequestBody @Validated({InsertValidGroup.class}) TestGeneratorDTO dto, BindingResult bindingResult) { testGeneratorService.insert(dto); } @PostMapping("/updateById") @ApiOperation(value = "修改测试生成") public void updateById(@RequestBody @Validated({UpdateValidGroup.class}) TestGeneratorDTO dto, BindingResult bindingResult) { testGeneratorService.updateById(dto); } @PostMapping("/findById/{id}") @ApiOperation(value = "根据id查询测试生成") public TestGenerator findById(@PathVariable Long id) { return testGeneratorService.findById(id); } @Pagination @PostMapping("/findAll") @ApiOperation(value = "查询测试生成列表") public List findAll(@RequestParam(defaultValue = AdminCommonConstant.PAGE_NUMBER) int pageNumber, @RequestParam(defaultValue = AdminCommonConstant.PAGE_SIZE) int pageSize, @RequestBody(required = false) TestGenerator testGenerator) { PageHelper.startPage(pageNumber, pageSize, "id desc"); return testGeneratorService.findAll(testGenerator); } @PostMapping("/deleteById/{id}") @ApiOperation(value = "根据id删除测试生成") public void deleteById(@PathVariable Long id) { testGeneratorService.deleteById(id); } } ``` #### entity文件 ```java package org.linitly.business.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.util.Date; import lombok.Data; import lombok.experimental.Accessors; import org.linitly.base.helper.entity.BaseEntity; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ @Data @Accessors(chain = true) @ApiModel(value = "测试生成") public class TestGenerator extends BaseEntity { @ApiModelProperty(value = "aaaaa") private String testAa; @ApiModelProperty(value = "bbbbb") private String testBb; @ApiModelProperty(value = "ccccc") private Integer testCc; @ApiModelProperty(value = "ddddd") private Long testDd; @ApiModelProperty(value = "eeeee") private Date testEe; @ApiModelProperty(value = "ffffff") private String testFf; @ApiModelProperty(value = "gggggg") private Double testGg; } ``` #### dto文件 ```java package org.linitly.business.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.*; import lombok.Data; import lombok.experimental.Accessors; import org.hibernate.validator.constraints.Range; import org.linitly.base.helper.entity.BaseDTO; import org.linitly.base.helper.groups.InsertValidGroup; import org.linitly.base.helper.groups.UpdateValidGroup; import org.linitly.business.constant.TestGeneratorConstant; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ @Data @Accessors(chain = true) @ApiModel(value = "测试生成DTO") public class TestGeneratorDTO extends BaseDTO { @ApiModelProperty(value = "aaaaa", required = true) @NotBlank(message = TestGeneratorConstant.TEST_AA_BLANK_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) @Size(max = TestGeneratorConstant.MAX_TEST_AA_SIZE, message = TestGeneratorConstant.TEST_AA_SIZE_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) private String testAa; @ApiModelProperty(value = "bbbbb") @Size(max = TestGeneratorConstant.MAX_TEST_BB_SIZE, message = TestGeneratorConstant.TEST_BB_SIZE_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) private String testBb; @ApiModelProperty(value = "ccccc") @Range(message = TestGeneratorConstant.TEST_CC_RANGE_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) private Integer testCc; @ApiModelProperty(value = "ddddd", required = true) @NotNull(message = TestGeneratorConstant.TEST_DD_BLANK_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) @Range(message = TestGeneratorConstant.TEST_DD_RANGE_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) private Long testDd; @ApiModelProperty(value = "eeeee") private java.util.Date testEe; @ApiModelProperty(value = "ffffff") @Size(max = TestGeneratorConstant.MAX_TEST_FF_SIZE, message = TestGeneratorConstant.TEST_FF_SIZE_ERROR, groups = {InsertValidGroup.class, UpdateValidGroup.class}) private String testFf; @ApiModelProperty(value = "gggggg", required = true) private Double testGg; } ``` #### vo文件 ```java package org.linitly.business.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.util.Date; import lombok.Data; import lombok.experimental.Accessors; import org.linitly.base.helper.entity.BaseVO; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ @Data @Accessors(chain = true) @ApiModel(value = "测试生成VO") public class TestGeneratorVO extends BaseVO { @ApiModelProperty(value = "aaaaa") private String testAa; @ApiModelProperty(value = "bbbbb") private String testBb; @ApiModelProperty(value = "ccccc") private Integer testCc; @ApiModelProperty(value = "ddddd") private Long testDd; @ApiModelProperty(value = "eeeee") private Date testEe; @ApiModelProperty(value = "ffffff") private String testFf; @ApiModelProperty(value = "gggggg") private Double testGg; } ``` #### constant文件 ```java package org.linitly.business.constant; /** * @author: linitly-generator * @date: 2022-03-11 09:31 * @description: */ public interface TestGeneratorConstant { String TEST_AA_BLANK_ERROR = "aaaaa不能为空"; int MAX_TEST_AA_SIZE = 16; String TEST_AA_SIZE_ERROR = "aaaaa长度不符合限制"; int MAX_TEST_BB_SIZE = 100; String TEST_BB_SIZE_ERROR = "bbbbb长度不符合限制"; String TEST_CC_RANGE_ERROR = "ccccc大小不符合限制"; String TEST_DD_BLANK_ERROR = "ddddd不能为空"; String TEST_DD_RANGE_ERROR = "ddddd大小不符合限制"; int MAX_TEST_FF_SIZE = 65535; String TEST_FF_SIZE_ERROR = "ffffff长度不符合限制"; } ``` ### 分支说明 `master`:开发分支,不建议使用; `数字版本`:为修改`mybatis-generator 1.4.0`源码后可使用RELEASE版本; `resource`:`mybatis-generator 1.4.0`版本源码备份; ### 配置说明 由于`xml`文件的格式是受`dtd`文件的规范和约束的,但无法去改变`mybatis`的`dtd`文件,且其本身提供的标签大部分仍要使用,所以仍基于`mybatis`的配置文件,在此基础上添加标签,使代码能正常读取运行。 新增`javaModelDtoGenerator`、`javaModelVoGenerator`、`javaControllerGenerator`、`javaServiceGenerator`、`javaConstantGenerator`标签;标签具有两个属性:`targetPackage`和`targetProject`,表示目标包名和目标目录;分别为生成DTO文件、VO文件、Controller文件、Service文件、Constant文件的配置。 新增`basePackage`标签,标签只有一个`name`属性,配置您的基础包名,上述标签的目标包名可在此基础包名之上简写。注意:**该标签需要在上述标签之前配置,不然会使用默认的基础包名`org.linitly.boot`** **重要:**由于代码的修改多数为硬编码,只为适应脚手架的需要而修改生成代码工具;且文件之间有关联性,因此建议使用者保持这些标签,如果需要修改,修改生成后的文件。 ### 代码说明 本人新增的代码文件位于`org.mybatis.generator.linitly`包下 #### 启动类 文件位于`org.mybatis.generator.api.ShellRunner`,主要代码位于`106-117`行; #### 读取配置 `org.mybatis.generator.config.xml.MyBatisGeneratorConfigurationParser`文件第81行代码:`parseConfiguration`方法,为读取配置文件信息的开始入口;读取主要配置文件信息的逻辑,在此文件的151行`parseContext`方法。 #### 读取数据库表信息 `org.mybatis.generator.internal.db.DatabaseIntrospector`文件第169行代码;`introspectTables`方法,为读取表信息的主要逻辑入口。 #### 获取文件信息 `org.mybatis.generator.config.Context`文件499行,`generateFiles`方法为获取要生成的文件的信息和主要入口。 #### 生成文件 `org.mybatis.generator.api.MyBatisGenerator`文件第275行代码,为生成文件的主要逻辑入口,`writeGeneratedJavaFile`方法和`writeGeneratedXmlFile`方法是生成java文件和xml文件的方法。 ### 主要文件 #### 注释文件 `org.mybatis.generator.internal.DefaultCommentGenerator`文件为默认注释的配置文件。 #### entity、vo文件 `org.mybatis.generator.codegen.mybatis3.model.BaseRecordGenerator`文件的`getCompilationUnits`方法为生成entity文件和vo文件的主要逻辑。 #### dao文件 `org.mybatis.generator.codegen.mybatis3.javamapper.JavaMapperGenerator`文件的`getCompilationUnits`方法为生成dao文件的主要逻辑。 #### mapper文件 `org.mybatis.generator.codegen.mybatis3.xmlmapper.XMLMapperGenerator`文件的`getSqlMapElement`方法为生成mapper文件的主要逻辑入口。 #### 其它文件 其它文件的主要逻辑见`org.mybatis.generator.linitly`包下对应的包下`Generator`文件。 ### 代码主要逻辑 1. 读取xml配置文件,将配置封装成配置文件并保存; 2. 通过数据库驱动,读取数据库表信息,封装成表信息并保存; 3. 通过获取的数据库表信息,循环获取要生成的文件信息,包括java文件、xml文件和kotlin文件,但kotlin文件我们基本不用,主要是前二者;封装成文件对象保存; 4. 循环获取到的文件,将文件信息读取并格式化成字符串,最后通过文件输出流写出文件;