# 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. 循环获取到的文件,将文件信息读取并格式化成字符串,最后通过文件输出流写出文件;