feat: 简化技术描述语言(1~2.6)

This commit is contained in:
dayjoy
2025-08-19 18:51:41 +08:00
parent 10af7636a9
commit bd1cf2a5a4

View File

@@ -1,71 +1,72 @@
<TOCO知识库> <TOCO知识库>
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
### **1. TOCO 平台概览:** ### **1. TOCO 平台概览:**
- **1.1 平台简介:** TOCO是一款重视软件设计及核心代码自动生成的专业研发平台。基于DDD、分层设计、CQRS等经典研发理论,数据库到API全部覆盖,可显著提升开发设计和编程效率,帮助开发团队实现更高的质量和生产力 - **1.1 平台简介:** TOCO是软件设计代码自动生成平台。基于DDD、分层架构、CQRS理论覆盖数据库到API的完整开发链路,提升开发效率和代码质量
- **1.2 核心价值/目标用户:** 从软件工程理论出发,提供软件设计能力,设计结果可直接转换为标准格式的代码,提编码一致性效率 - **1.2 核心价值/目标用户:** 提供软件设计能力,设计成果直接生成标准代码,提编码一致性效率
- **1.3 主要特性概览:** 可视化设计、模型关联、多人协作、代码生成器 - **1.3 主要特性概览:** 可视化设计、模型关联、多人协作、代码生成器
### **2. TOCO 设计元素:** ### **2. TOCO 设计元素:**
#### **2.1 模块 (Module)** #### **2.1 模块 (Module)**
- **定义与用途:** 在TOCO中我们将系统领域细分为具体的模块映射为Java工程中的module。这些模块代表了系统的叶子子域每个模块负责特定的功能。模块划分有助于系统的可维护性和可扩展性并能提高开发效率和代码质量 - **定义与用途:** 在TOCO中我们将系统领域细分为具体的模块映射为Java工程中的module。这些模块代表了系统的叶子子域每个模块负责特定的功能。模块划分有助于系统的可维护性和可扩展性并能提高开发效率和代码质量
- **关键配置:** 名称(小写英文字母+下划线如meeting,user_detail,禁止加任何固定后缀,全局唯一),描述 - **关键配置:** 名称(小写英文+下划线如meeting,user_detail禁止后缀全局唯一),描述
- **与其他元素关系:** 下面的每种设计元素都属于个模块 - **与其他元素关系:** 下列所有设计元素都属于个模块
- **代码产物** 每个Module会单独生成一个Java Module项目路径/modules/模块名,内部采用了entrance、service、manager、persist、common分层结构 - **代码产物:** 生成独立Java Module项目路径/modules/模块名,包含entrance、service、manager、persist、common分层
#### **2.2 枚举 (Enum)** #### **2.2 枚举 (Enum)**
- **定义与用途:** Enum用来表达一些常量值集合,可被其他模块使用,可被用来做为字段类型 - **定义与用途:** 表示常量值集合,可模块使用,可为字段类型
- **关键属性/配置:** 名称(以_enum结尾,全局唯一),枚举值列表(全大写字母+下划线) - **关键属性/配置:** 名称(以_enum结尾全局唯一),枚举值列表(全大写+下划线)
- **与其他元素关系:** 枚举可以作为其他对象(Entity、Dto、Vo、Bto、Qto、Eo)的字段类型使用。 - **与其他元素关系:** 可作为Entity、Dto、Vo、Bto、Qto、Eo的字段类型
- **Enum设计元素的表达:** - **Enum设计元素的表达:**
- Json格式表达json schema 定义如下 - Json格式schema如下
```json ```json
{ {
"type": "object", "type": "object",
"properties": { "properties": {
"name": { "type": "string","description": "名称,使用英语表达,单词之间使用下划线分割,总长度不能超过32字符"}, "name": { "type": "string","description": "名称,英语表达,下划线分割,超过32字符"},
"uuid": { "type": "string","description": "计元素Enum)在TOCO中的唯一标识符,创建枚举的时候,该字段为空; 在更新时,该字段不能为空"}, "uuid": { "type": "string","description": "唯一标识符,创建时为空,更新时必填"},
"description": { "type": "string", "description": "描述这个枚举的具体含义,介绍这个枚举的用途,控制在128字符以内"}, "description": { "type": "string", "description": "枚举含义和用途,不超过128字符"},
"moduleName": { "type": "string", "description": "指定该设计元素(Enum)所属模块,创建的时候该字段不能为空,在更新的时候,该字段可以为空"}, "moduleName": { "type": "string", "description": "所属模块,创建时必填,更新时可空"},
"values": { "values": {
"type": "array","description": "枚举值列表", "type": "array","description": "枚举值列表",
"items": {"type": "string","description": "枚举值,使用英语表达, 单词之间使用下划线分割,总长度不能超过32字符"} "items": {"type": "string","description": "枚举值,英语表达下划线分割,超过32字符"}
} }
}, },
"required":["name","description"] "required":["name","description"]
} }
``` ```
* **代码产物和修改建议** * **代码产物和修改建议**
* **生成产物**:在common模块中生成一个Java类 * **生成产物:** common模块中生成Java类
* **职责:** 表达Enum数据结构 * **职责:** 表达Enum数据结构
* **命名规则**类名以Enum结尾 * **命名规则:** 类名以Enum结尾
* **类路径** 位于 <code>**.common.enums</code> 包路径 * **类路径:** 位于 <code>**.common.enums</code> 包下
* **唯一标识符位置** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Enum在TOCO中的uuid}|ENUM|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则: ${Enum的uuid}|ENUM|DEFINITION
- **生成代码** Enum会在common层生成Enum文件如StatusEnum - **生成代码:** 在common层生成Enum文件如StatusEnum
- **修改建议** 不建议修改 - **修改建议:** 不建议修改
#### **2.3 值对象 (EO)** #### **2.3 值对象 (EO)**
- **定义与用途:** EO为一种POJO对象结构,可被其他模块使用,可被用来做为实体字段类型。 - **定义与用途** EO是可复用的POJO数据结构,可模块使用,可为实体字段类型。
- **关键属性/配置:** 名称(以_eo结尾,全局唯一)。EO的字段类型只能为基本类型(含List、EO、Enum,其他类型不允许 - **关键属性/配置** 名称以_eo结尾全局唯一字段类型限制:基本类型List、EO、Enum。
- **与其他元素关系:** 可作为其他对象(Entity、Dto、Vo、Bto、Qto)的字段类型使用同时一个EO中可以嵌套其他EO作为字段类型 - **与其他元素关系** 可作为Entity、Dto、Vo、Bto、Qto的字段类型支持EO嵌套
- **EO设计元素的表达:** - **EO设计元素的表达**
- Json格式表达Json Schema定义如下 - 使用Json格式表达Schema定义如下
```json ```json
{ {
"type":"object", "type":"object",
"properties": { "properties": {
"name":{ "type": "string", "description": "名称,使用英语表达,单词之间使用下划线分割,总长度不能超过32字符"}, "name":{ "type": "string", "description": "名称,英文下划线分割,超过32字符"},
"description": { "type": "string","description": "描述,描述这个数据结构的具体含义,介绍这个数据结构的用途,控制在128字符以内"}, "description": { "type": "string","description": "描述EO含义和用途不超过128字符"},
"uuid":{ "type": "string", "description": "该设计在TOCO中的唯一标识符,创建EO的时候该字段为空; 在更新时,该字段不能为空"}, "uuid":{ "type": "string", "description": "唯一标识符,创建时为空,更新时必填"},
"moduleName":{ "type": "string", "description": "指定该设计元素所属模块,创建的时候该字段不能为空,在更新的时候,该字段可以为空"}, "moduleName":{ "type": "string", "description": "所属模块,创建时必填,更新时可空"},
"fieldList":{ "fieldList":{
"type":"array", "description": "定义EO属性字段列表", "type":"array", "description": "EO属性字段列表",
"items":{ "items":{
"type": "object", "type": "object",
"properties":{ "properties":{
"name": { "type": "string","description": "属性字段名称,使用英语表达,单词之间使用下划线分割,总长度不能超过32字符"}, "name": { "type": "string","description": "字段名称,英文下划线分割,超过32字符"},
"uuid":{ "type": "string","description": "字段类型是枚举、值对象的时候,该字段不能为空,表示该字段对应的枚举或者值对象" } , "uuid":{ "type": "string","description": "字段类型为Enum或Eo时必填对应的Enum或Eo标识符" } ,
"type":{ "type": "string","description": "字段类型,可以是String,Integer,Long,Float,Double,Boolean,Date,Eo,Enum, BigDecimal,List" }, "type":{ "type": "string","description": "字段类型String,Integer,Long,Float,Double,Boolean,Date,Eo,Enum,BigDecimal,List" },
"innerUuid":{"type": "string", "description": "当innerTypeEo或Enum的时候,表示字段类型对应的枚举或者值对象"}, "innerUuid":{"type": "string", "description": "当innerTypeEo或Enum时,对应的标识符"},
"innerType": { "type": "string", "description": "当type是List的时候表示List包含的元素类型, 类型可以是String,Integer,Long,Float,Double,Boolean,Date,Eo,Enum, BigDecimal"} "innerType": { "type": "string", "description": "List元素类型String,Integer,Long,Float,Double,Boolean,Date,Eo,Enum,BigDecimal"}
}, },
"required":[ "name","type"] "required":[ "name","type"]
} }
@@ -75,125 +76,134 @@
} }
``` ```
* **代码产物和修改建议** * **代码产物和修改建议**
* **生成产物**:在persist层生成结构定义类如AddressEo * **生成产物** persist层生成结构定义类如AddressEo
* **职责:** 表达POJO数据结构 * **职责** 表达POJO数据结构
* **命名规则**类名以Eo结尾 * **命名规则** 类名以Eo结尾
* **类路径:** 位于 <code>**.persist.eo</code> 包路径 * **类路径:** 位于 `**.persist.eo` 包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Eo在TOCO中的uuid}|EO|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则${Eo的uuid}|EO|DEFINITION
- **修改建议:** 不建议修改 - **修改建议:** 不建议修改
#### **2.4 实体关系 (ER / Entity)** #### **2.4 实体关系 (ER / Entity)**
- **定义与用途:** 实体及其关系。一个实体一般对应一个数据库表,关系为实体间的外键依赖关系 - **定义与用途:** 实体对应数据库表,关系为实体间的外键依赖
- **关键属性/配置:** 实体中包含名称、字段、字段类型、主键、索引关系分为1:1和1:N关系 - **关键属性/配置:** 包含名称、字段、字段类型、主键、索引关系分为1:1和1:N
- **与其他元素关系:** 实体关系是聚合的基础也是DTO和VO的派生基础 - **与其他元素关系:** 实体是聚合的基础也是DTO和VO的派生基础
- **代码产物和修改建议** - **代码产物和修改建议**
- 结构定义 - 结构定义
* **生成产物**Java类按照Mybatis-plus要求生成 * **生成产物**Mybatis-plus要求生成的Java类
* **职责:** 按照Mybatis-plus的要求生成结构定义类文件 * **职责:** 生成Mybatis-plus结构定义类文件
* **类路径:** 位于 <code>**.persist.dos</code> 包路径 * **类路径:** 位于 `**.persist.dos` 包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则: ${Entity的uuid}|ENTITY|DEFINITION
- Mapper - Mapper
* **生成产物**persist层生成Mybatis-plusMapper类 * **生成产物**persist层Mybatis-plus Mapper类
* **职责:** 提供Mapper给Mybatis-plus框架 * **职责:** Mybatis-plus框架提供Mapper
* **命名规则**类名以Mapper结尾(${entityName}Mapper) * **命名规则**类名以Mapper结尾(${entityName}Mapper)
* **类路径:** 位于 <code>**.persist.mapper.mybatis</code> 包路径 * **类路径:** 位于 `**.persist.mapper.mybatis` 包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Eo在TOCO中的uuid} * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则: ${Entity的uuid}|ENTITY|MAPPER
- Dao接口 - Dao接口
* **生成产物**persist层生成Dao接口 * **生成产物**persist层Dao接口
* **职责:** 提供Entity数据查询接口为service层提供数据访问入口 * **职责:** 提供Entity数据查询接口为service层提供数据访问入口
* **命名规则**类名以Dao结尾(${entityName}Dao) * **命名规则**类名以Dao结尾(${entityName}Dao)
* **类路径:** 位于<code>**.persist.mapper</code> 包路径 * **类路径:** 位于 `**.persist.mapper` 包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|IDAO * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则: ${Entity的uuid}|ENTITY|IDAO
- Dao实现 - Dao实现
* **生成产物**persist层生成Dao接口实现类文件 * **生成产物**persist层Dao接口实现类
* **职责:** 通过调用Mapper实现实现Dao接口 * **职责:** 通过调用Mapper实现Dao接口
* **命名规则**类名以DaoImpl结尾(${entityName}DaoImpl) * **命名规则**类名以DaoImpl结尾(${entityName}DaoImpl)
* **类路径:** 位于 <code>**.persist.mapper</code> 包路径 * **类路径:** 位于 `**.persist.mapper` 包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|ENTITY|DAO * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则: ${Entity的uuid}|ENTITY|DAO
- **修改建议:** 不建议修改 - **修改建议:** 不建议修改
#### **2.5 聚合对象 (BO/业务对象)** #### **2.5 聚合对象 (BO/业务对象)**
- **定义与用途:** 在TOCO中聚合对象是对一组密切关联实体的封装。聚合对象从单一实体开始,这个实体我们称为聚合根,通过实体间关系,不断的顺序将其他实体按层级关系组装进这个聚合对象。聚合对象可以按实体表达为树形结构。聚合对象提供了这组实体的内存一致性视图,提供数据操作入口。由于写操作的内聚性,聚合对象只能在单一模块中组合而且一个实体只能属于一个对象。同样如果有实体不在任何一个聚合对象中TOCO将无法提供与之相关的写方法 - **定义与用途:** 聚合对象封装一组关联实体。从聚合根实体开始,按层级关系组装其他实体,形成树形结构。提供内存一致性视图数据操作入口。一个实体只能属于一个聚合对象,聚合对象只能在单一模块中组合。
- **包含元素:** 聚合对象包括聚合根及其聚合下的其他子实体对象例如,商品聚合ProductBO中,商品基本信息实体是ProductBO的聚合根商品SKU实体、商品库存实体是ProductBO的子聚合对象。 - **包含元素:** 聚合根实体 + 子实体对象例如ProductBO包含商品基本信息实体(聚合根)、商品SKU实体、商品库存实体(子对象)
- **关键配置:** 名称(${EntityName驼峰}BO结尾如StaffBO),聚合根实体,聚合子对象实体。每个聚合必须包含一个聚合根 - **关键配置:** 名称(${EntityName驼峰}BO如StaffBO),聚合根实体,子对象实体。每个聚合必须包含一个聚合根
- **与其他元素关系:** 聚合是写方案的基础 - **与其他元素关系:** 聚合是写方案的基础
- **代码产物和修改建议** - **代码产物和修改建议**
- 综述 - 综述
- 业务对象包含多个Entity通过业务对象的嵌套组合表达Entity之间的关系,如果一个业务对象包含了子对象,则会生成BO和BaseBO,BaseBO封装实体属性和关系子类留给业务扩展逻辑; - 业务对象包含多个Entity通过嵌套组合表达Entity关系。有子对象时生成BO和BaseBOBaseBO封装实体属性和关系BO用于业务扩展。无子对象时只生成BO类。
如果是叶子节点不存在子对象的BO则直接生成BO类文件不生成BaseBO类文件
- BO - BO
* **生成产物**Manager层生成聚合对象类文件符合Hibernate标准 * **生成产物**Manager层生成聚合对象类符合Hibernate标准
* **职责:** 定义聚合对象,多个聚合对象组合成层级结构实现充血模型,支持写链路上的数据变更监听数据变更,支持数据校验 * **职责:** 定义聚合对象,组合成层级结构实现充血模型,支持写链路数据变更监听变更、数据校验
* **命名规则**类名以BO结尾(${entityName}BO) * **命名规则**${entityName}BO
* **类路径:** 位于 <code>**.manager.bo</code> 包路径 * **类路径:** `**.manager.bo`包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|BO|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中uuid规则: ${Entity的uuid}|BO|DEFINITION
- **修改建议:** 建议修改BO中的validateAggregate或valid方法。不建议修改验方法以外的其他代码,如果发现需求中有业务不变性校验,**注意** 上述的校验方法,在写方案内部由框架触发调用,而不是业务代码显式调用 - **修改建议:** 建议修改BO中的validateAggregate或valid方法进行业务不变性校验。不建议修改验方法以外的代码。校验方法由框架自动调用,不需要业务代码显式调用
- BaseBO - BaseBO
* **生成产物**对于存在子BO的聚合对象,封装不变代码部分 * **生成产物**存在子BO时生成,封装不变代码部分
* **职责:** 定义聚合对象,多个聚合对象组合成层级结构实现充血模型,支持写链路上的数据变更监听数据变更,支持数据校验 * **职责:** 定义聚合对象,组合成层级结构实现充血模型,支持写链路数据变更监听变更、数据校验
* **命名规则**类名以BO结尾(${entityName}BO) * **命名规则**${entityName}BO
* **类路径:** 位于<code>**.manager.bo</code> 包路径 * **类路径:** `**.manager.bo`包
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定 ,uuid规则: ${Entity在TOCO中的uuid}|BO|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中uuid规则: ${Entity的uuid}|BO|DEFINITION
- **修改建议:** 建议修改BO中的validateAggregate或valid方法,如果发现需求中有业务不变性校验;不建议修改验方法以外的其他代码 - **修改建议:** 建议修改BO中的validateAggregate或valid方法进行业务不变性校验不建议修改验方法以外的代码
#### **2.6 数据传输对象 (DTO)** #### **2.6 数据传输对象 (DTO)**
- **定义与用途:** 在TOCO中DTO表达某个Entity为基本,通过外键关系不断关联多个Entity的数据结构。DTO还隐式表达了数据的取数拼装,这种拼装符合外键关系。DTO分为BaseDTO和普通DTOBaseDTO派生自Entity包含Entity所有字段每个Entity有且仅有一个BaseDTO普通DTO派生自BaseDTO包含BaseDTO所有字段,且可以增加扩展字段或自定义字段。注意DTO不能作为接口参数,不能作为HTTP API返回值 - **定义与用途:** DTO基于某个Entity构建通过外键关系关联多个Entity的数据结构。DTO隐含数据组装逻辑,符合外键关系。分为BaseDTO和普通DTOBaseDTO直接派生自Entity包含Entity所有字段每个Entity有一个BaseDTO普通DTO基于BaseDTO创建包含BaseDTO所有字段增加扩展字段或自定义字段。DTO不能作为接口参数不能作为HTTP API返回值
- **如何创建/生成:** 对于每个EntityTOCO会自动生成一个BaseDTO命名为${Entity名字}BaseDto如UserBaseDto该BaseDTO包含Entity全部字段。除了BaseDTO其他DTO均需要手动以BaseDTO为根来创建。在TOCO中必须要先判断需要的DTO是否为BaseDTO如果是BaseDTO则可通过Entity名称获取BaseDTO如果不是BaseDTO则需要通过DTO要表达的信息创建DTO,如会议及议程信息。 - **创建方式:** 每个Entity自动生成一个BaseDTO命名为${Entity名字}BaseDto如UserBaseDto包含Entity全部字段。其他DTO需手动基于BaseDTO创建。判断是否为BaseDTO是则通过Entity名称获取否则通过DTO要表达的信息创建如会议及议程信息。
- **关键配置:** 名称(BaseDTO以BaseDto结尾其他DTO以Dto结尾,全局唯一)、根Entity、字段列表。DTO中的字段分三种a.继承Entity或BaseDTO的字段和Entity及BaseDTO的字段类型一样b.扩展字段含正向替换和反向注入字段类型为DTO或List<DTO>;c.自定义字段类型为基本类型、Eo、Enum、DTO类型。BaseDTO中一般包含Entity全部字段,DTO中一般包含BaseDTO中的全部字段,不进行字段裁剪,可以根据外键关系扩展其他Entity(详见**字段扩展方式**)在明确无法扩展外部Entity的情况下可增加对应的自定义字段。 - **关键配置:** 名称BaseDTO以BaseDto结尾其他DTO以Dto结尾全局唯一、根Entity、字段列表。字段分三种a.继承Entity或BaseDTO的字段类型相同b.扩展字段,含正向替换和反向注入字段类型为DTO或List<DTO>c.自定义字段类型为基本类型、Eo、Enum、DTO。BaseDTO包含Entity全部字段DTO包含BaseDTO全部字段裁剪字段,可通过外键关系扩展其他Entity,无法扩展时可增加自定义字段。
- **字段扩展方式:**TOCO定义了一个DTO组装方法适用于DTO通过外键关系替换/注入对应Entity的信息对象化表达有外键关系的Entity信息。只要存在外键关系且满足以下条件可扩展a.对于正向替换:当前实体存在指向其他实体的外键字段b.对于反向注入:其他实体存在指向当前实体的外键字段。 - **字段扩展方式:** DTO通过外键关系替换/注入对应Entity信息。满足条件可扩展a.正向替换:当前实体指向其他实体的外键字段b.反向注入:其他实体指向当前实体的外键字段。
例如有两个Entity
<code> 例如两个Entity
```
MeetingRoom{ //会议室 MeetingRoom{ //会议室
Long id;// 会议室id,主键 Long id;// 会议室id,主键
String name;// 会议室名称 String name;// 会议室名称
} }
Meeting { //会议 Meeting { //会议
Long id;// 会议id,主键 Long id;// 会议id,主键
Long roomid; //占用的会议室id到MeetingRoom的外键,n:1关系 Long roomid; //会议室id外键到MeetingRoom的n:1关系
Long backupRoomid; //备用会议室id到MeetingRoom的外键,n:1关系 Long backupRoomid; //备用会议室id外键到MeetingRoom的n:1关系
String title; //会议标题 String title; //会议标题
DateTime startTime //会议开始时间 DateTime startTime; //开始时间
DateTime endTime //会议结束时间 DateTime endTime; //结束时间
} }
</code> ```
其中Meeting和MeetingRoom是n:1关系。即多个会议室会占用同一个会议室。
当组装对象以某Entity为根时那么首先它将拥有和该Entity一样的数据结构并将通过下面的“正向替换”“反向注入”的行为递归的将多个互相之间有外键关系的Entity的信息组装到该组装对象中 Meeting和MeetingRoom是n:1关系。多个会议占用同一个会议室
定义“正向替换”这个行为,选定一个表,这张表存在到另外一张表的一个或多个外键。选择和需求相关的具体的外键属性,将该外键属性替换为另一张表为根的组装对象。这样就可以获取基于某些外键且包含另一张表更详细的属性数据 组装对象以某Entity为根时首先拥有该Entity相同数据结构通过"正向替换"、"反向注入"行为递归组装有外键关系的Entity信息
例如需要会议和其占用会议室时将Meeting表中的roomid外键替换为以MeetingRoom为根的组装对象而backupRoomid对应的候选会议室具体信息和本需求无关不做任何替换。如下 **正向替换:** 选定表存在到另一表的外键。选择相关的外键属性,将该外键替换为另一表为根的组装对象。获取基于外键且包含另一表详细属性的数据。
<code> 例如需要会议和占用会议室时将Meeting表中roomid外键替换为以MeetingRoom为根的组装对象backupRoomid不替换
```
MeetingWithRoomDto { MeetingWithRoomDto {
Long id;// 会议id Long id;// 会议id
MeetingRoomDto room { //正向替换该会议用的会议室信息,是一个以会议室为根的对象 MeetingRoomDto room { //正向替换会议室信息,以会议室为根的对象
Long id; //会议室ID Long id; //会议室ID
String name;// 会议室名称 String name;// 会议室名称
} }
Long backupRoomid; // 不变化 Long backupRoomid; // 不变化
String title; //会议标题 String title; //会议标题
DateTime startTime //会议开始时间 DateTime startTime; //开始时间
DateTime endTime //会议结束时间 DateTime endTime; //结束时间
} }
</code> ```
又例如需要会议和其候选会议室时将Meeting表中的backupRoomid进行正向替换。
又例如需要会议且即需要其占用会议室也需要候选会议室时将Meeting表中的roomidbackupRoomid都进行正向替换 **反向注入:** 选定表如有其他表到该表有外键选择相关的外键属性在选定表中增加以另一表为根的组合对象1:1时或组合对象列表n:1时
同时TOCO还定义了“反向注入”这个行为选定一个表如果有另外的表到前表有外键选择和需求相关的具体的外键属性在选定表中增加一个以另外表为根的组合对象(当外键关系是1:1时)或者组合对象的列表(当外键关系是n:1时)。需求是:“获取会议室和占用它的会议信息”,需要选定MeetingRoom那么基于另外的表Meeting存在字段roomid为到MeetingRoom的n:1关系外键。可以将List<MeetingBaseDto>反向注入到MeetingRoom中最终生成一个以Meeting为根的组装对象生成 需求:"获取会议室和占用它的会议信息"选定MeetingRoom基于Meeting存在roomid字段为到MeetingRoom的n:1外键。将List<MeetingBaseDto>反向注入到MeetingRoom中
<code>
```
MeetingRoomWithMeetingDto { MeetingRoomWithMeetingDto {
Long id;// 会议室id Long id;// 会议室id
String name;// 会议室名称 String name;// 会议室名称
List<MeetingBaseDto> meetingList { //反向注入用该会议室的会议信息,是以会议为根的对象 List<MeetingBaseDto> meetingList { //反向注入使用该会议室的会议信息
Long id;// 会议id Long id;// 会议id
String title; //会议标题 String title; //会议标题
DateTime startTime //会议开始时间 DateTime startTime; //开始时间
DateTime endTime //会议结束时间 DateTime endTime; //结束时间
} }
} }
</code> ```
这种“正向替换”和“反向注入”可以按需递归调用去将多个互相之间有外键关系的对象组装成最终对象。例如还有另外一张表MeetingAgenda到Meeting有n:1的外键和另外一张表AgendaAttendance到MeetingAgenda有n:1外键。那么如果我要去组装以Meeting开始包含MeetingRoom, MeetingAgenda, AgendaAttendance的组装对象首先发现MeetingRoom是可以正向扩展到Meeting的反向注入MeetingAgenda而AgendaAttendance需要先反向注入到MeetingAgenda中。
- **TOCO中DTO的json结构描述:** 在TOCO中DTO使用一个json结构表示该结构可用于理解DTO的含义或作为创建、更新DTO工具的参数。部分字段的含义为dto的uuid为唯一标识如果需要创建DTO则设置为null如果需要复用则填入其uuid。expandList为正向替换reverseExpandList为反向注入customFieldList为自定义字段。expandListList中foreignKeyInThisEntity为正向替换对应的本表外键字段的名字dtoFieldName为正向替换之后给该字段的起的新名字reverseExpandList中foreignKeyInOtherEntity为反向注入对应的他表外键字段的名字dtoFieldName为反向注入之后给该字段的起的新名字customFieldList中uuid为自定义字段特有的UUID创建DTO的时候不需要填入因为TOCO会自动为其分配UUID更新DTO的时候需要传入用于定位需要更新的自定义字段typeUuid参数对应类结构的UUID当type为Enum、Eo时包含该字段innerType为List内部类型当type为List时包含该字段innerUuid为List内部类结构的UUID当type为List且innerType=Enum、Eo时包含该字段。示例如下 "正向替换"和"反向注入"可按需递归调用,组装多个有外键关系的对象。
- **JSON结构描述:** DTO用json结构表示用于理解含义或作为创建、更新DTO工具的参数。字段含义dto的uuid为唯一标识创建时设置为null复用时填入uuid。expandList为正向替换reverseExpandList为反向注入customFieldList为自定义字段。expandList中foreignKeyInThisEntity为本表外键字段名dtoFieldName为替换后字段名reverseExpandList中foreignKeyInOtherEntity为他表外键字段名dtoFieldName为注入后字段名customFieldList中uuid为自定义字段UUID创建时不填入更新时需传入用于定位typeUuid为类结构UUIDtype为Enum、Eo时包含innerType为List内部类型type为List时包含innerUuid为List内部类结构UUIDtype为List且innerType为Enum、Eo时包含。
示例:
- meeting_with_room_dto - meeting_with_room_dto
<code> ```json
{ {
"dto": { "dto": {
"uuid": null, "uuid": null,
"name": "meeting_with_room_dto", "name": "meeting_with_room_dto",
"description": "会议详情,包含会议室信息,以及其中的会议列表", "description": "会议详情,包含会议室信息",
"fromEntity": "meeting", "fromEntity": "meeting",
"expandList": [ "expandList": [
{ {
@@ -209,7 +219,7 @@ DateTime endTime //会议结束时间
], ],
"customFieldList":[ "customFieldList":[
{ {
"uuid": "自定义字段唯一标识更新DTO的时候需要传入", "uuid": "自定义字段唯一标识更新DTO时需传入",
"name": "status", "name": "status",
"type": "Enum", "type": "Enum",
"typeUuid": "对应Enum的uuid", "typeUuid": "对应Enum的uuid",
@@ -218,15 +228,16 @@ DateTime endTime //会议结束时间
] ]
} }
} }
</code> ```
- meeting_room_with_meetings_dto - meeting_room_with_meetings_dto
<code> ```json
{ {
"dto": { "dto": {
"uuid": "d05c7b3d-1c92-45a1-2113-a01b245813c1", "uuid": "d05c7b3d-1c92-45a1-2113-a01b245813c1",
"name": "meeting_room_with_meetings_dto", "name": "meeting_room_with_meetings_dto",
"description": "会议室详情,包含会议室信息,以及其中的会议信息", "description": "会议室详情,包含会议信息",
"fromEntity": "meeting", "fromEntity": "meeting_room",
"reverseExpandList": [ "reverseExpandList": [
{ {
"foreignKeyInOtherEntity": "room_id", "foreignKeyInOtherEntity": "room_id",
@@ -241,49 +252,51 @@ DateTime endTime //会议结束时间
] ]
} }
} }
</code> ```
示例中meeting_with_room_dto没有uuid为待创建的DTO。meeting_base_dto和meeting_room_with_meetings_dto为已存在的DTO带有uuid。
- **预定义方法:** 对于每一个DTOTOCO会自动其根Entity的唯一索引生成一些预定义的RPC方法及实现预定义方法不仅获取了根Entity的数据还通过RPC调用的方式**自动**获取了**所有扩展字段**的数据并对数据进行了拼装处理。如实体user有unique index(username)则会针对UserDto生成UserDto UserDtoService.getByUserName(String userName)和List<UserDto> UserDtoService.getByUserNames(List<String> userNames)。预定义方法内部根据外键关系自动生成了复杂DTO数据的递归、Join拼装的能力会直接返回DTO内部的所有继承字段和扩展字段的数据。注意自定义字段的数据获取不会自动生成需要在对应的convert方法中编写代码 meeting_with_room_dto无uuid为待创建DTO。meeting_base_dto和meeting_room_with_meetings_dto为已存在DTO带uuid
- **公开性:** DTO可以设置公开性如果DTO为公开则其生成的预定义RPC方法也为公开RPC可以被其他模块订阅并调用如果DTO为非公开则其生成的预定义RPC方法也为非公开RPC其他模块不可见
- **跨模块依赖:** 如果DTO内引用了其他模块的DTO则需要订阅其他模块的RPC(getBy${PrimaryKey},getBy${PrimaryKey}s,getBy${foreignKey}等)方法用来获取对应的DTO
- **复杂嵌套DTO获取流程:** 如果我们需要获取DTO通常有2种方式且两种方式都可以直接获取到复杂嵌套的DTO数据
- 第1种: 通过预定义方法获取DTO
- 第2种: 通过读方案获取DTO
在TOCO中通常使用以下步骤判断使用哪种方式 - **预定义方法:** 每个DTO基于根Entity的唯一索引自动生成预定义RPC方法及实现预定义方法获取根Entity数据通过RPC自动获取所有扩展字段数据并拼装。如实体user有唯一索引username则为UserDto生成UserDto UserDtoService.getByUserName(String userName)和List<UserDto> UserDtoService.getByUserNames(List<String> userNames)。预定义方法内部基于外键关系自动生成复杂DTO数据的递归、Join拼装能力直接返回DTO内部所有继承字段和扩展字段数据。自定义字段数据获取不自动生成需在对应convert方法中编写代码。
- a. 如果查询DTO的条件为主键或唯一索引的值或列表则直接使用第1种方式 - **公开性:** DTO可设置公开性DTO为公开时生成的预定义RPC方法也为公开RPC可被其他模块订阅调用DTO为非公开时生成的预定义RPC方法也为非公开RPC其他模块不可见。
- b. 如果通过其他复杂查询条件则可以采用第2种方式 - **跨模块依赖:** 如DTO内引用其他模块DTO需订阅其他模块RPC方法getBy${PrimaryKey}、getBy${PrimaryKey}s、getBy${foreignKey}等用于获取对应DTO。
- **复杂嵌套DTO获取流程:** 获取DTO有2种方式都可直接获取复杂嵌套DTO数据
- 第1种通过预定义方法获取DTO
- 第2种通过读方案获取DTO
判断使用方式的步骤:
- a. 查询DTO条件为主键或唯一索引的值或列表使用第1种方式
- b. 通过其他复杂查询条件采用第2种方式
判断使用方式时只能根据查询条件判断是否使用读方案禁止使用返回值是否需要数据拼装来判断如现实代码和TOCO定义有冲突只能使用TOCO定义
注意判断使用哪种方式时,只能根据查询条件判断是否使用读方案,绝对禁止使用返回值是否需要数据拼装来判断!**如果现实中的代码和TOCO中的步骤有冲突时只能使用TOCO的定义**
- **代码产物和修改建议** - **代码产物和修改建议**
- 结构定义 - 结构定义
* **生成产物**一个Java类 * **生成产物**Java类
* **职责:** 表达DTO数据结构 * **职责:** 表达DTO数据结构
* **命名规则**类名以Dto结尾 * **命名规则**类名以Dto结尾
* **禁止** 修改该类 * **禁止** 修改该类
* **类路径:** 位于 <code>**.manager.dto</code> 包路径下 * **类路径:** `**.manager.dto` 包路径下
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|DEFINITION * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则${DTO在TOCO中的uuid}|DTO|DEFINITION
- **Manager** - **Manager**
* **生成产物:** Java接口及实现类 * **生成产物:** Java接口及实现类
* **命名规则:** 接口类名以Manager结尾、实现类名以ManagerImpl结尾(${DtoName}Manager)、基类名ManagerBaseImpl结尾(${DtoName}ManagerImpl) * **命名规则:** 接口类名以Manager结尾、实现类名以ManagerImpl结尾(${DtoName}Manager)、基类名ManagerBaseImpl结尾(${DtoName}ManagerImpl)
* **职责:** 提供DTO数据获取接口包括根据id单个、id列表批量获取、以及根据DTO对应实体的数据库索引获取 * **职责:** 提供DTO数据获取接口包括根据id单个、id列表批量获取、根据DTO对应实体的数据库索引获取
* **类路径:** 位于<code>**.manager</code> 包路径下 * **类路径:** `**.manager` 包路径下
* **禁止** 删除该类中任何系统自动生成函数 * **禁止** 删除该类中任何系统自动生成函数
* **唯一标识符位置:** 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|MANAGER * **唯一标识符位置:** 类注解@AutoGenerated中指定uuid规则${DTO在TOCO中的uuid}|DTO|MANAGER
- **Converter** - **Converter**
* **生成产物:** Java实现类及基类 * **生成产物:** Java实现类及基类
* **禁止** 删除该类中任何系统自动生成函数 * **禁止** 删除该类中任何系统自动生成函数
* **命名规则:** 实现类名以Converter结尾(${DtoName}Converter)、基类名以BaseConverter结尾(${DtoName}BaseConverter) * **命名规则:** 实现类名以Converter结尾(${DtoName}Converter)、基类名以BaseConverter结尾(${DtoName}BaseConverter)
* **职责:** Entity转换到BaseDTO或BaseDTO转为普通DTO从Entity转为BaseDTO的方法命名为convert${EntityName}To${DtoName}从BaseDTO转换为DTO的方法命名为convert${BaseDtoName}To${DtoName} * **职责:** Entity转换到BaseDTO或BaseDTO转为普通DTO从Entity转为BaseDTO的方法命名为convert${EntityName}To${DtoName}从BaseDTO转换为DTO的方法命名为convert${BaseDtoName}To${DtoName}
* **类路径:** 位于 <code>**.manager.converter</code> 包路径下 * **类路径:** `**.manager.converter` 包路径下
* **唯一标识符位置:** * **唯一标识符位置:**
* 实现类Converter 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|CONVERTER * 实现类Converter类注解@AutoGenerated中指定uuid规则${DTO在TOCO中的uuid}|DTO|CONVERTER
* 基类BaseConverter 其对应的唯一标志在类注解@AutoGenerated中指定,uuid规则: ${DTO在TOCO中的uuid}|DTO|BASE_CONVERTER * 基类BaseConverter类注解@AutoGenerated中指定uuid规则${DTO在TOCO中的uuid}|DTO|BASE_CONVERTER
- **例子:** - **例子:**
* 如UserDto、UserDtoManager、UserDtoConverter extends UserDtoBaseConverter、UserDtoService(名称为${DtoName}Service内部包含getBy${PrimaryKey},getBy${PrimaryKey}s等方法。如Dto为UserBaseDto则生成类名为UserBaseDtoService * 如UserDto、UserDtoManager、UserDtoConverter extends UserDtoBaseConverter、UserDtoService名称为${DtoName}Service内部包含getBy${PrimaryKey}getBy${PrimaryKey}s等方法。如Dto为UserBaseDto则生成类名为UserBaseDtoService
- **修改建议:** - **修改建议:**
- 建议在Service与BaseConverter中进行代码扩展不建议修改结构定义文件和Manager文件。其中DTO的**自定义字段**由于不直接派生自Entity所以一般对应取数逻辑代码。通常如果涉及数据获取、计算和拼装,批量处理性能最好,所以代码位置**必须**放在BaseConverter中已自动生成的**列表**转换方法中批量取数组装如UserBaseDtoBaseConverter.convertUserToUserBaseDto(List<User>)或UserDtoBaseConverter.convertUserBaseDtoToUserDto(List<UserBaseDto>) - 建议在Service与BaseConverter中扩展代码不建议修改结构定义文件和Manager文件。DTO的自定义字段不直接派生自Entity一般对应取数逻辑代码。涉及数据获取、计算和拼装批量处理性能最好代码位置必须放在BaseConverter中已自动生成的列表转换方法中批量取数组装如UserBaseDtoBaseConverter.convertUserToUserBaseDto(List<User>)或UserDtoBaseConverter.convertUserBaseDtoToUserDto(List<UserBaseDto>)
#### **2.7 视图对象 (VO)** #### **2.7 视图对象 (VO)**
- **定义与用途:** 在TOCO中VO表达某个BaseDTO(如果用户指明派生源也可使用其他DTO)为派生源通过外键关系不断关联多个BaseDTO的数据结构。VO用于在视图层与前端之间进行数据传输往往被当做HTTP API的返回值、或读方案的返回值使用由服务端返回至前端。注意VO不能作为接口的参数也不能作为RPC的返回值。 - **定义与用途:** 在TOCO中VO表达某个BaseDTO(如果用户指明派生源也可使用其他DTO)为派生源通过外键关系不断关联多个BaseDTO的数据结构。VO用于在视图层与前端之间进行数据传输往往被当做HTTP API的返回值、或读方案的返回值使用由服务端返回至前端。注意VO不能作为接口的参数也不能作为RPC的返回值。