dto-creator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Preflight: Spring MCP

前置检查:Spring MCP

This skill is part of the Spring Agent Toolkit and is designed to work with the Spring MCP server (provided by the Amplicode IntelliJ plugin). Before doing anything else, check your tool list for any Spring MCP tool — they are exposed under the
amplicode
MCP server (e.g.
get_project_summary
,
list_module_dependencies
,
get_entity_details
); harnesses that flatten MCP tools into the tool list use the
mcp__amplicode__
prefix on the same names.
  • If at least one Amplicode tool is available — MCP is connected. Proceed with the skill below.
  • If none are available — stop and invoke the
    amplicode-install
    skill (bundled with the Spring Agent Toolkit). It installs the Amplicode plugin and walks the user through the «Настроить Spring Agent» welcome-screen button + MCP-client restart. After it completes, the MCP tools become available — resume this skill.
  • If
    amplicode-install
    is not registered in your skill list, tell the user (in their language): "This skill needs the Amplicode IntelliJ plugin and its MCP server. Install it from https://amplicode.ru/marketplace into IntelliJ IDEA Ultimate/Community or GigaIDE, open any project, click «Настроить Spring Agent» on the Amplicode welcome screen, then restart your MCP client."

此技能是Spring Agent Toolkit的一部分,旨在与Spring MCP server(由Amplicode IntelliJ插件提供)配合使用。在进行任何操作之前,请检查你的工具列表中是否有Spring MCP工具——它们在
amplicode
MCP服务器下暴露(例如
get_project_summary
list_module_dependencies
get_entity_details
);将MCP工具扁平化到工具列表的封装器会在相同名称前添加
mcp__amplicode__
前缀。
  • 如果至少有一个Amplicode工具可用——MCP已连接。继续使用下方技能。
  • 如果没有可用的Amplicode工具——停止操作并调用**
    amplicode-install
    **技能(随Spring Agent Toolkit捆绑提供)。它会安装Amplicode插件,并引导用户完成«Настроить Spring Agent»欢迎屏幕按钮操作 + MCP客户端重启。完成后,MCP工具将可用——恢复此技能。
  • 如果你的技能列表中未注册
    amplicode-install
    ,请用用户的语言告知:"此技能需要Amplicode IntelliJ插件及其MCP服务器。请从https://amplicode.ru/marketplace安装到IntelliJ IDEA Ultimate/Community或GigaIDE,打开任意项目,点击Amplicode欢迎屏幕上的«Настроить Spring Agent»,然后重启你的MCP客户端。"

DTO Creator

DTO生成器

Creates a DTO class (Java class, Java record, Java+Lombok, or Kotlin data class) for an entity with selected attributes, constructors, getters/setters, equals/hashCode, toString, and optional features.

CRITICAL: Code ONLY from examples/ files. If no matching example -- STOP and ask user. CRITICAL: For questions with a fixed set of choices, prefer
AskUserQuestion
> its analogue > plain text list. Plain numbered text lists are the last resort when no interactive tool is available.
CRITICAL: Read the conversation context BEFORE running Step 1. Half the questions in Steps 2–7 may already be answered by the user's prompt and prior turns. Re-asking what was already said is the #1 reason this skill feels slow. Step 7 (mapper) is automatic when conversion is needed. If from context it is clear that the DTO will be used in code that converts entities to/from DTOs (controller, service, endpoint replacement, etc.), the skill MUST delegate to
mapper-creator
— never write manual mapping code inline. The
mapper-creator
skill decides the implementation (MapStruct, Custom, adding dependencies) — this skill just delegates.

为实体创建包含选定属性、构造函数、getter/setter方法、equals/hashCode方法、toString方法及可选特性的DTO类(Java类、Java record、Java+Lombok或Kotlin数据类)。

重要提示:仅从examples/文件中生成代码。如果没有匹配的示例——停止操作并询问用户。 重要提示:对于有固定选项的问题,优先使用
AskUserQuestion
工具 > 同类工具 > 纯文本列表。只有在没有交互式工具可用时,才将纯编号文本列表作为最后手段。
**重要提示:在运行步骤1之前,请阅读对话上下文。**步骤2-7中的一半问题可能已经由用户的提示和之前的对话回合回答过。重复询问已提及的内容是导致此技能使用体验拖沓的首要原因。 **步骤7(映射器)在需要转换时自动触发。**如果从上下文可以明确DTO将用于实体与DTO相互转换的代码中(控制器、服务、端点替换等),则此技能必须委托给
mapper-creator
——绝不要手动编写内联映射代码。
mapper-creator
技能会决定实现方式(MapStruct、自定义实现、添加依赖)——此技能仅负责委托。

Defaults

默认设置

OptionDefaultAlways ask?Notes
entity--YESmain branching: which entity to create DTO for
attributesall entity fieldsYESwhich fields to include
className
{EntityName}Dto
NOsuggest, confirm only
languagefrom
get_project_summary
NOauto-detected
variantauto from language + depsYESJava class / Java record / Java+Lombok / Kotlin
mutablefalseNOskip unless user wants customization
allArgsConstructortrueNOJava plain only
equalsHashCodetrueNOJava plain only
toStringtrueNOJava plain only
fluentSettersfalseNOonly when mutable=true, Java only
jsonIgnoreUnknownPropertiesfalseNOJava only, when Jackson on classpath
serializableTypeNoSerializableNOrarely needed
packageNamesame package as entityNOauto-detected
subDtoType (per ToOne association)FLAT with id-only subYESFour options available: New Class / New Nested Class / Existing Class / Flat. "Only ID" does NOT exist as a separate option — it is Flat with only the sub-entity
id
checked. See
references/sub-dto.md
.
subDtoType (per ToMany / collection)NEW_NESTED_CLASSYESsame 4 options as ToOne. Flat IS supported for collections and produces composite plural fields like
Set<Integer> specialtyIds
— see
references/sub-dto.md
.
fieldNameOverride (per field)noneNOper-field rename
extraValidations (per field)noneNOuser-added jakarta validators on top of inherited ones
removedValidations (per field)noneNOconstraints inherited from entity that the user wants dropped
indentfrom
.editorconfig
(fallback 4-space)
NOsee § Indentation below
Smart defaults: If user says "use defaults", "all defaults", "default settings", or similar -- skip ALL questions where "Always ask?" = NO. Only ask mandatory questions.
Smart answer recognition: When user provides a value instead of choosing from a numbered list, accept it directly. Examples:
  • Question "Which entity?" -> user answers "Order" -> this IS the entity, don't re-ask
  • Question "Variant?" -> user answers "record" -> this IS Java record, don't show options
  • If user provides multiple answers in one message -> accept all, skip answered questions
  • NEVER ask a question that the user already answered (even implicitly)
Batch questions: Group closely related questions into a single
AskUserQuestion
call (up to 4 questions per call) when they:
  • Belong to the same logical section (e.g. both are Java method generation settings)
  • Don't depend on each other's answers
  • Have obvious defaults that the user can skip
Rules:
  • Maximum 3-4 questions per
    AskUserQuestion
    call
  • Mark the recommended option with
    (Recommended)
    and place it first
  • Never batch questions from DIFFERENT decision branches
  • The primary branching question (entity selection, variant) is always asked ALONE
  • Prefer
    AskUserQuestion
    for choices; fall back to plain text lists only if the tool is unavailable

选项默认值是否必须询问?说明
entity--主要分支:为哪个实体创建DTO
attributes实体的所有字段要包含哪些字段
className
{EntityName}Dto
给出建议,仅需确认
language来自
get_project_summary
自动检测
variant根据语言和依赖自动选择Java类 / Java record / Java+Lombok / Kotlin
mutablefalse除非用户需要自定义,否则跳过
allArgsConstructortrue仅适用于纯Java类
equalsHashCodetrue仅适用于纯Java类
toStringtrue仅适用于纯Java类
fluentSettersfalse仅在mutable=true且为Java时可用
jsonIgnoreUnknownPropertiesfalse仅适用于Java,当类路径上存在Jackson时
serializableTypeNoSerializable很少需要
packageName与实体相同的包自动检测
subDtoType(针对一对一关联)FLAT仅包含子实体ID有四个选项可用:新类 / 新嵌套类 / 现有类 / 扁平化。“仅ID”并非独立选项——它是仅勾选子实体
id
的扁平化模式。请参阅
references/sub-dto.md
subDtoType(针对一对多/集合关联)NEW_NESTED_CLASS与一对一关联的四个选项相同。集合支持扁平化模式,会生成复合复数字段,例如
Set<Integer> specialtyIds
——请参阅
references/sub-dto.md
fieldNameOverride(针对单个字段)按字段重命名
extraValidations(针对单个字段)用户在继承的校验规则之上添加的jakarta校验器
removedValidations(针对单个字段)用户希望移除的、从实体继承的约束
indent来自
.editorconfig
(默认回退为4空格)
请参阅下方“缩进”部分
**智能默认值:**如果用户说“使用默认值”、“全部默认”、“默认设置”或类似表述——跳过所有“是否必须询问?”为“否”的问题。仅询问必填问题。
**智能答案识别:**当用户提供值而非从编号列表中选择时,直接接受该值。示例:
  • 问题“选择哪个实体?”→ 用户回答“Order”→ 这就是目标实体,无需重新询问
  • 问题“选择哪种类型?”→ 用户回答“record”→ 这就是Java record,无需展示选项
  • 如果用户在一条消息中提供多个答案→ 全部接受,跳过已回答的问题
  • 绝不要询问用户已经回答过的问题(即使是隐含回答)
**批量提问:**将密切相关的问题分组到单个
AskUserQuestion
调用中(每次调用最多4个问题),当这些问题:
  • 属于同一逻辑部分(例如均为Java方法生成设置)
  • 彼此独立,不依赖对方的答案
  • 有明确的默认值供用户跳过
规则:
  • 每次
    AskUserQuestion
    调用最多包含3-4个问题
  • 将推荐选项标记为
    (推荐)
    并放在首位
  • 绝不将不同决策分支的问题批量处理
  • 主要分支问题(实体选择、类型选择)始终单独询问
  • 优先使用
    AskUserQuestion
    进行选择;仅当工具不可用时才回退到纯文本列表

Decision-making principle — context first, then ask

决策原则——优先参考上下文,再询问

Before asking the user any question, attempt to derive the answer from the context already gathered: project summary, module dependencies, entity details, existing files in the package, prior turns of this conversation, and the user's original prompt. Only ask when the context yields no clear default or when the choice is genuinely user-specific (e.g. which entity, which fields).
Hierarchy of decisions:
  1. Context is unambiguous → decide silently, do NOT ask. Examples: language and JDK from
    get_project_summary
    ; Lombok / Jackson / Hibernate Validator from
    list_module_dependencies
    ; package from the entity FQN; className from
    {Entity}Dto
    ; back-reference
    @ManyToOne
    filtering; auto-selection of sub-entity scalars; record vs. plain class when JDK ≥ 16 and no Lombok and the user did not request otherwise. Exception: subDtoType is NEVER decided silently — it always requires at minimum principle 2 (one-line confirmation), unless the USER explicitly stated the shape in their own message (not in ARGUMENTS).
  2. Context gives a strong signal → state the decision + alternatives in one line, let the user override or stay silent. Format:
    Will create `ScheduleTemplateDto` as a Java record with nested `SlotDto` (record).
    Alternatives: plain class, Lombok, separate file for SlotDto. OK?
    The user can answer "ok" / "yes" / silence → accept; or name an alternative → switch. This is not the same as the numbered question format — it is a single confirmation line.
  3. Context yields no clear default → ask with
    AskUserQuestion
    (preferred) or its analogue, with the recommended option first.
    When
    AskUserQuestion
    is available, use it with
    preview
    fields so the user sees the concrete code shape for each option. Mark the recommended option with
    (Recommended)
    in its label and place it first. If no interactive choice tool is available, fall back to a plain text list. Never ask iteratively ("which variant?" → user picks → "which fields?" → …) when one batched call would do.
  4. Context is fully empty for a critical input → ask plainly. This applies to: which entity, which fields (when not "all"), the user's intent itself.
在向用户提出任何问题之前,尝试从已收集的上下文推导答案:项目摘要、模块依赖、实体详情、包中的现有文件、本次对话的历史回合以及用户的原始提示。仅当上下文无法得出明确默认值或选择确实由用户决定时(例如选择哪个实体、哪些字段),才进行询问。
决策层级:
  1. 上下文明确→静默决策,不询问。 示例:从
    get_project_summary
    获取语言和JDK版本;从
    list_module_dependencies
    获取Lombok/Jackson/Hibernate Validator;从实体全限定名获取包名;从
    {Entity}Dto
    获取类名;过滤反向引用
    @ManyToOne
    ;自动选择子实体标量;当JDK ≥16且无Lombok且用户未作其他要求时,自动选择record而非纯类。 例外:subDtoType绝不会静默决策——至少需要遵循原则2(单行确认),除非用户在自己的消息中明确说明格式(而非在参数中)。
  2. 上下文给出强烈信号→说明决策+替代方案,允许用户覆盖或保持沉默。 格式:
    将创建`ScheduleTemplateDto`作为Java record,并嵌套`SlotDto`(record类型)。
    替代方案:纯类、Lombok、为SlotDto创建单独文件。是否确认?
    用户可以回答“ok”/“yes”/保持沉默→接受;或指定替代方案→切换。这与编号问题格式不同——它是单行确认问题。
  3. 上下文无明确默认值→使用
    AskUserQuestion
    (优先)或同类工具询问,推荐选项放在首位。
    AskUserQuestion
    可用时,使用带
    preview
    字段的工具,让用户看到每个选项对应的具体代码形状。将推荐选项标记为
    (推荐)
    并放在首位。如果没有交互式选择工具可用,回退到纯文本列表。 绝不要在一次批量调用即可完成的情况下,逐个询问(“选择哪种类型?”→用户选择→“选择哪些字段?”→……)
  4. 关键输入的上下文完全为空→直接询问。 适用于:选择哪个实体、哪些字段(非“全部”)、用户的意图本身。

How to ask — prefer
AskUserQuestion

询问方式——优先使用
AskUserQuestion

When a question must be asked, prefer the
AskUserQuestion
tool (or its analogue) over writing a numbered list in the response body. Fall back to plain text only if no interactive choice tool is available.
Rules for
AskUserQuestion
calls in this skill:
  • Each call may contain up to 4 questions that are independent of each other (the tool will render them together). Use this to batch related decisions in one round-trip.
  • Each question has 2–4 options. The tool auto-adds an "Other" choice for free-form input — never include it manually.
  • Mark the recommended option by putting it first with
    (Recommended)
    appended to the label.
  • Use
    multiSelect: true
    for "which fields to include" or "which validators to add" — anything where multiple answers are valid.
  • header
    is a 12-char chip label (e.g. "Variant", "Sub-DTO", "Fields").
  • Each option has a
    description
    explaining what the choice means or its consequence (one short sentence).
When
AskUserQuestion
is not the right tool:
  • Free-form input where there is no enumerable set of options (e.g. arbitrary class name, arbitrary field rename) — ask in plain text.
  • The "single confirmation line" form from principle 2 — that is a plain question with an obvious yes/no, not an enumerated choice.
The screen-driven question lists in Steps 2–5 below are a fallback for case 4. They are NOT a script to execute top-to-bottom. If a question's answer is already determined by principles 1–3, skip the question. Plugin-wizard fidelity is not a goal — generation correctness is. The plugin's UI exists because a screen can show many controls at once; a chat cannot, so the skill must compensate by deciding more on its own.

当必须提问时,优先使用**
AskUserQuestion
**工具(或同类工具),而非在响应体中编写编号列表。仅当没有交互式选择工具可用时才回退到纯文本。
此技能中
AskUserQuestion
调用的规则:
  • 每次调用可包含最多4个独立问题(工具会将它们一起呈现)。使用此方式将相关决策批量处理,减少往返次数。
  • 每个问题有2-4个选项。工具会自动添加“其他”选项用于自由输入——无需手动添加。
  • 将推荐选项放在首位,并在标签后附加
    (推荐)
  • 对于“要包含哪些字段”或“要添加哪些校验器”等允许多选的问题,设置
    multiSelect: true
  • header
    是12字符以内的标签(例如“类型”、“子DTO”、“字段”)。
  • 每个选项有
    description
    ,说明该选择的含义或后果(简短句子)。
AskUserQuestion
不适用时:
  • 自由输入且无枚举选项(例如任意类名、任意字段重命名)→直接用纯文本询问。
  • 原则2中的“单行确认”形式→这是带有明确是/否的简单问题,而非枚举选择。
下方步骤2-5中的屏幕驱动问题列表是回退方案,适用于情况4。它们并非必须从上到下执行的脚本。如果问题的答案已通过原则1-3确定,跳过该问题。插件向导的保真度不是目标——生成正确性才是。插件的UI存在是因为屏幕可以同时显示多个控件;而聊天无法做到,因此技能必须自行做出更多决策来弥补这一点。

Step 0 -- Conversation context first (REQUIRED, no tool calls)

步骤0 —— 优先参考对话上下文(必填,无需调用工具)

Before any MCP call, before any question, re-read the user's prompt and the prior turns of this conversation and extract whatever is already stated. This step costs nothing and prevents the most common failure mode of this skill — asking the user something they already said.
Build a mental checklist of inputs and tick off everything the user has already provided, explicitly or implicitly:
InputLook for in the prompt / context
entitya class name (
Vet
,
Owner
,
ScheduleTemplate
); "for X"; an open file in the IDE; a file path; a recently discussed entity in this conversation
purpose"for REST", "for controller", "for API", "for mapping", "projection", "for service" — drives field selection and the mapper question
fields"all fields", "only id and name", "without password", "with associations", "flat"
variant"record", "plain class", "Lombok", "data class" — also implied by language: Kotlin → data class, no question
mapper"and mapper", "with mapper", "only DTO", "no mapper"
className"name it
OwnerSummaryDto
", "class
Foo
"
package"in package
", "next to controller"
smart defaults"use defaults", "all defaults", "default settings", "as usual"
sub-DTO shape"nested", "separate class", "only id", "flat"
prior project factslanguage, JDK, dependencies — already known if discussed earlier in this conversation; do not re-fetch
For every input that is explicitly or strongly implicitly answered: mark it as decided and skip the corresponding question in Steps 2–7. Do NOT ask "what entity?" if the user wrote "create DTO for Vet" —
Vet
is the answer. Do NOT ask "Java record or class?" if the user wrote "make record DtoX" — record is the answer.
For every input that is not answered: defer to the Decision-making principle below — try to derive it from project context first (Step 1), and only then ask.
CRITICAL: ARGUMENTS ≠ user intent. The ARGUMENTS block at the bottom of this prompt is written by the invoking assistant, NOT by the user. It may contain the assistant's own analysis, assumptions, or field-level details that the user never stated. When determining what the user "already said", look ONLY at the actual user messages in the conversation history — never treat ARGUMENTS as a substitute for user input. In particular, do NOT skip asking about sub-DTO shape just because ARGUMENTS describes one.
Step 0 is mental, not a tool call. Do not announce it to the user. Do not write "Step 0 done". Just internalize what the user already said before proceeding to Step 1.

在调用任何MCP工具、提出任何问题之前,重新阅读用户的提示和本次对话的历史回合,提取已明确说明的信息。此步骤无需成本,可避免此技能最常见的失败模式——询问用户已提及的内容。
构建输入清单,勾选用户已明确或隐含提供的所有内容:
输入项在提示/上下文中查找的内容
entity类名(
Vet
Owner
ScheduleTemplate
);“为X创建”;IDE中打开的文件;文件路径;本次对话中最近讨论的实体
purpose“用于REST”、“用于控制器”、“用于API”、“用于映射”、“投影”、“用于服务”——驱动字段选择和映射器问题
fields“所有字段”、“仅id和name”、“不含password”、“包含关联”、“扁平化”
variant“record”、“纯类”、“Lombok”、“数据类”——也可由语言隐含:Kotlin→数据类,无需询问
mapper“并生成映射器”、“带映射器”、“仅生成DTO”、“不要映射器”
className“命名为
OwnerSummaryDto
”、“类
Foo
package“在包
中”、“放在控制器旁边”
智能默认值“使用默认值”、“全部默认”、“默认设置”、“照常”
子DTO格式“嵌套”、“单独类”、“仅id”、“扁平化”
现有项目信息语言、JDK、依赖——如果本次对话之前已讨论过,无需重新获取
对于明确或强烈隐含回答的每个输入项:标记为已确定,跳过步骤2-7中对应的问题。如果用户写了“为Vet创建DTO”,不要询问“选择哪个实体?”——
Vet
就是答案。如果用户写了“创建record类型的DtoX”,不要询问“Java record还是类?”——record就是答案。
对于未回答的每个输入项:遵循下方的决策原则——首先尝试从项目上下文推导(步骤1),然后再询问。
**重要提示:参数≠用户意图。**此提示底部的ARGUMENTS块由调用助手编写,而非用户。它可能包含助手自身的分析、假设或用户从未提及的字段级细节。在确定用户“已提及内容”时,仅查看对话历史中的实际用户消息——绝不要将ARGUMENTS视为用户输入的替代品。特别是,不要仅因为ARGUMENTS描述了某种格式就跳过询问子DTO格式。
步骤0是心理步骤,无需调用工具。不要向用户宣布此步骤,不要写“步骤0完成”。只需在继续步骤1之前,内化用户已提及的内容。

Step 1 -- Gather minimal project context (automatic, no questions)

步骤1 —— 收集最少项目上下文(自动执行,无需提问)

Call only the MCP tools whose result is actually consumed by a later step. Do not pre-fetch "in case we need it" — every variable here must have a concrete downstream user.
ToolVariableUsed for
get_project_summary
language
,
jdkVersion
,
moduleName
language → variant selection (Step 4) and reference file (java vs kotlin); jdkVersion →
canUseRecords = jdkVersion >= 16
; moduleName → multi-module disambiguation + parameter for
list_module_dependencies
list_module_dependencies(moduleName)
presentDeps
derived flags below — Lombok/Jackson/Validation feature gates
That is the entire Step 1. Do NOT fetch:
  • springBootVersion
    /
    bootMajor
    — no branching depends on it
  • buildFile
    — DTO generation does not edit the build file (no dependencies to add); a DTO needs only language constructs
  • mainPackage
    — the DTO's package is derived from the entity's FQN, not from the project root
  • list_application_properties_files
    /
    propsFile
    — DTO writes nothing to
    application.properties
  • list_all_domain_entities
    — needed only if the user did not name an entity in their prompt. Defer to Step 2 as a lazy fallback.
  • get_entity_details
    /
    list_entity_dtos
    — depend on knowing the entity, which happens in Step 2. Defer to Step 2.
Derived variables (all from
presentDeps
and
get_project_summary
):
  • hasLombok
    =
    presentDeps
    contains
    lombok
  • hasJackson
    =
    presentDeps
    contains
    jackson-databind
    or
    jackson-core
  • hasValidation
    =
    presentDeps
    contains
    hibernate-validator
    or
    jakarta.validation-api
    or
    spring-boot-starter-validation
  • canUseRecords
    =
    language == JAVA
    AND
    jdkVersion >= 16
If multi-module project (multiple modules in
get_project_summary
): Ask which module to use. Then re-call
list_module_dependencies
for that module.

仅调用结果会在后续步骤中实际使用的MCP工具。不要预先获取“以防需要”的信息——此处的每个变量必须有明确的下游用途。
工具变量用途
get_project_summary
language
jdkVersion
moduleName
language→类型选择(步骤4)和参考文件(java vs kotlin);jdkVersion→
canUseRecords = jdkVersion >= 16
;moduleName→多模块歧义消除 +
list_module_dependencies
的参数
list_module_dependencies(moduleName)
presentDeps
推导下方标记——Lombok/Jackson/Validation功能开关
以上就是步骤1的全部内容。不要获取:
  • springBootVersion
    /
    bootMajor
    ——没有分支逻辑依赖它
  • buildFile
    ——DTO生成不会修改构建文件(无需添加依赖);DTO仅需语言构造
  • mainPackage
    ——DTO的包由实体的全限定名推导,而非项目根目录
  • list_application_properties_files
    /
    propsFile
    ——DTO不会向
    application.properties
    写入任何内容
  • list_all_domain_entities
    ——仅当用户在提示中未指定实体时才需要。回退到步骤2作为延迟方案。
  • get_entity_details
    /
    list_entity_dtos
    ——依赖于已知实体,这会在步骤2中完成。延迟到步骤2执行。
推导变量(均来自
presentDeps
get_project_summary
):
  • hasLombok
    =
    presentDeps
    包含
    lombok
  • hasJackson
    =
    presentDeps
    包含
    jackson-databind
    jackson-core
  • hasValidation
    =
    presentDeps
    包含
    hibernate-validator
    jakarta.validation-api
    spring-boot-starter-validation
  • canUseRecords
    =
    language == JAVA
    jdkVersion >= 16
如果是多模块项目(
get_project_summary
中有多个模块):询问要使用哪个模块。然后重新调用该模块的
list_module_dependencies

Step 2 -- Entity selection

步骤2 —— 实体选择

By Step 0 you should already know the entity if the user mentioned it. Most common case: the user wrote "create DTO for
Vet
" → entity is
Vet
, skip the question, go straight to the parallel fetch below.
Lazy fallback — only when entity is unknown: call
list_all_domain_entities(moduleName)
entities
, then ask via
AskUserQuestion
(options = entity names from the list, max 4; if more than 4 entities, use the 4 most likely candidates based on context and add a note that the user can type a different name via "Other").
This is the only place
list_all_domain_entities
should be called. If the user named the entity in their prompt, do NOT call it.
After the entity FQN is known, call (in parallel):
ToolVariableUsed for
get_entity_details(entityFqn)
entityDetails
Step 3 attribute selection, association analysis, validation inheritance, generation order in every variant reference
list_entity_dtos(entityFqn)
for the parent entity is NOT called here — it has no downstream consumer. Sub-entity calls (
list_entity_dtos(subEntityFqn)
) are still needed for
EXIST_CLASS
detection in
references/sub-dto.md
, but they are lazy and per-association, fired only when the user is offered the EXIST_CLASS option. See
references/sub-dto.md
for the exact place.
DTO name collision is handled by a different lazy call —
list_existing_classes(package)
— fired right before generation in Step 6 (see anti-hallucination checklist). It is not part of Step 2.

通过步骤0,你应该已经知道用户提及的实体。最常见的情况:用户写了“为
Vet
创建DTO”→实体是
Vet
,跳过问题,直接执行下方的并行获取。
**延迟回退方案——仅当实体未知时:**调用
list_all_domain_entities(moduleName)
entities
,然后通过
AskUserQuestion
询问(选项=列表中的实体名称,最多4个;如果实体超过4个,根据上下文选择4个最可能的候选者,并添加注释说明用户可通过“其他”输入不同名称)。
这是唯一应该调用
list_all_domain_entities
的场景。如果用户在提示中指定了实体,不要调用它。
在确定实体全限定名后,并行调用:
工具变量用途
get_entity_details(entityFqn)
entityDetails
步骤3的属性选择、关联分析、校验继承、每种类型参考中的生成顺序
此处不调用父实体的
list_entity_dtos(entityFqn)
——它没有下游用途。子实体调用(
list_entity_dtos(subEntityFqn)
)仍需用于
references/sub-dto.md
中的
EXIST_CLASS
检测,但会延迟执行,仅当向用户提供EXIST_CLASS选项时才触发。请参阅
references/sub-dto.md
中的具体位置。
DTO名称冲突由另一个延迟调用处理——
list_existing_classes(package)
——在步骤6生成前触发(请参阅防幻觉检查清单)。它不属于步骤2。

Step 3 -- Attribute selection

步骤3 —— 属性选择

Default: include every scalar attribute and every association (with the sub-DTO defaults from
references/sub-dto.md
). Ask only when context signals that the user wants something narrower.
默认:包含所有标量属性和所有关联(使用
references/sub-dto.md
中的子DTO默认设置)。仅当上下文表明用户需要更窄范围时才询问。

Decide from context (preferred over asking)

优先从上下文决策(优于询问)

Use the purpose captured in Step 0 to pick a sensible default set:
Purpose signalDefault field set
"for REST", "for controller", "for API"all scalars + all associations expanded (NEW_NESTED_CLASS for ToMany, FLAT id for ToOne) — the user wants the response shape, including related data
"projection", "summary", "list view", "for list"scalars only, ToOne associations as Flat id, ToMany excluded
"for mapping", "for service", "DTO for storage"all scalars + all associations expanded
"only id and name" / explicit field listexactly what the user named, nothing else
no purpose signalall scalars + all associations expanded (richest reasonable default)
If the chosen default matches the user's apparent intent, do not ask. Just generate. State the choice in the one-line confirmation form (principle 2) at most.
使用步骤0中捕获的用途选择合理的默认字段集:
用途信号默认字段集
“用于REST”、“用于控制器”、“用于API”所有标量 + 所有关联展开(一对多关联使用NEW_NESTED_CLASS,一对一关联使用扁平化ID)——用户需要响应格式,包括相关数据
“投影”、“摘要”、“列表视图”、“用于列表”仅标量,一对一关联作为扁平化ID,一对多关联排除
“用于映射”、“用于服务”、“用于存储的DTO”所有标量 + 所有关联展开
“仅id和name” / 明确字段列表完全按照用户指定的内容,无其他字段
无用途信号所有标量 + 所有关联展开(最丰富的合理默认值)
如果所选默认值符合用户的明显意图,不要询问。直接生成。最多以原则2的单行确认形式说明选择。

When to ask

何时询问

Ask only if:
  • The user explicitly said "choose fields" / "ask about fields" / "fine-tune settings", OR
  • The entity has many fields and the purpose signal is ambiguous AND the user did not say "use defaults".
When asking, use
AskUserQuestion
with
multiSelect: true
:
QuestionHeaderOptions (first = recommended)
Which fields to include in DTO
{Entity}Dto
?
FieldsAll fields + associations (Recommended) / Scalars only / Only id and name / Specify manually
For each association included, apply the sub-DTO defaults from
references/sub-dto.md
. Do NOT ask per-association unless the user explicitly requested fine-grained control.

仅在以下情况询问:
  • 用户明确说“选择字段”/“询问字段”/“微调设置”,或者
  • 实体有很多字段且用途信号不明确,且用户未说“使用默认值”。
询问时,使用
multiSelect: true
AskUserQuestion
问题标题选项(首位为推荐)
要在DTO
{Entity}Dto
中包含哪些字段?
字段所有字段+关联(推荐) / 仅标量 / 仅id和name / 手动指定
对于每个包含的关联,应用
references/sub-dto.md
中的子DTO默认设置。除非用户明确要求细粒度控制,否则不要逐个询问关联。

Step 4 -- Variant selection

步骤4 —— 类型选择

Apply the Decision-making principle above. The variant is almost always derivable from context — explicit asking should be the exception, not the default.
If language=KOTLIN: route to
references/kotlin.md
. No question.
If language=JAVA: decide as follows.
ContextActionVariant
hasLombok = true
AND user prompt explicitly mentions Lombok
decide silently
references/java-lombok.md
canUseRecords = true
AND
hasLombok = false
AND user did not ask for mutability/setters/Lombok
decide silently, mention in the one-line confirmation from principle 2
references/java-record.md
canUseRecords = false
AND
hasLombok = false
decide silently
references/java-plain.md
hasLombok = true
AND
canUseRecords = true
AND user gave no signal
use the one-line confirmation form (principle 2): "Will create as Java record (JDK ≥ 16, no Lombok). Alternatives: plain class, Lombok. OK?"depends on answer
User explicitly said "plain class" / "mutable" / "with setters"decide silently
references/java-plain.md
User explicitly said "record"decide silently
references/java-record.md
User explicitly said "Lombok"decide silently (only if
hasLombok = true
; otherwise warn and fall back)
references/java-lombok.md
Only fall back to the full numbered question when none of the rows above matches AND the user has not said "use defaults". Even then, prefer the "all variants with default marked" format from principle 3 over an iterative question.
Map answer to variant:
  • plain →
    references/java-plain.md
  • record →
    references/java-record.md
  • Lombok →
    references/java-lombok.md

应用上述决策原则。类型几乎总是可以从上下文推导出来——明确询问应该是例外,而非默认。
**如果language=KOTLIN:**参考
references/kotlin.md
。无需询问。
**如果language=JAVA:**按以下方式决策。
上下文操作类型
hasLombok = true
且用户提示明确提及Lombok
静默决策
references/java-lombok.md
canUseRecords = true
hasLombok = false
且用户未要求可变性/setter/Lombok
静默决策,在原则2的单行确认中提及
references/java-record.md
canUseRecords = false
hasLombok = false
静默决策
references/java-plain.md
hasLombok = true
canUseRecords = true
且用户未给出信号
使用原则2的单行确认形式:“将创建为Java record(JDK ≥16,无Lombok)。替代方案:纯类、Lombok。是否确认?”根据回答决定
用户明确说“纯类”/“可变性”/“带setter”静默决策
references/java-plain.md
用户明确说“record”静默决策
references/java-record.md
用户明确说“Lombok”静默决策(仅当
hasLombok = true
时;否则警告并回退)
references/java-lombok.md
仅当以上所有行都不匹配且用户未说“使用默认值”时,才回退到完整的编号问题。即使如此,优先使用原则3中的“所有类型+标记默认值”格式,而非逐个询问。
答案映射到类型:
  • plain →
    references/java-plain.md
  • record →
    references/java-record.md
  • Lombok →
    references/java-lombok.md

Step 5 -- Variant-specific questions

步骤5 —— 类型特定问题

Follow the variant-specific questions from the selected reference file. Only ask if user did NOT say "all defaults".

遵循所选参考文件中的类型特定问题。仅当用户未说“全部默认”时才询问。

Step 6 -- Generate code

步骤6 —— 生成代码

  1. Determine target path:
    src/main/{java|kotlin}/{packagePath}/{className}.{java|kt}
  2. Follow the Generation Order from the selected reference file.
  3. For each step:
    If skeleton (new file):
    • Read the skeleton
      .md
      from
      examples/_skeletons/
    • Apply variable substitutions
    • Use Write tool to create the file
    If fragment:
    • Read the fragment
      .md
      from
      examples/_fragments/
    • Read the Insert Point to know WHERE to insert
    • Use Edit tool to insert code at the specified point
    • Apply variable substitutions
  4. Variable substitution rules:
    • {packageName}
      -> from entity package or user choice
    • {className}
      -> from user or default
      {EntityName}Dto
    • Field-level variables -> from entity details
    • NEVER substitute anything not listed in Variables
    • NEVER add imports, methods, or code not in the example
    • FQN handling (CRITICAL): examples contain FQNs (e.g.
      java.util.Objects
      ,
      java.util.List
      ,
      jakarta.validation.constraints.NotNull
      ). When writing the final file, you MUST:
      1. Replace every FQN in the body of the class with its short name (e.g.
        java.util.Objects.hash(...)
        ->
        Objects.hash(...)
        ,
        java.util.List<Integer>
        ->
        List<Integer>
        ,
        @jakarta.validation.constraints.NotNull
        ->
        @NotNull
        ).
      2. Collect every FQN you shortened and emit a corresponding
        import
        line right after the
        package
        statement, sorted, no duplicates.
      3. Types from
        java.lang
        (
        String
        ,
        Integer
        ,
        Object
        , ...) must NOT be imported and must appear as short names.
      4. Classes from the same package as the DTO must NOT be imported.
      5. Javadoc
        {@link ...}
        references — UNIFORM:
        Generate short name + import in
        {@link …}
        for every shape: top-level Java class, top-level Java record, nested static class, nested record, and separate-file sub-DTO (NEW_CLASS). There is no asymmetry. Always shorten the entity reference and always add the corresponding
        import
        line (unless the entity is in the same package).
      6. Group imports in two blocks separated by ONE blank line:
        • Block 1 — all third-party / project imports together:
          jakarta.*
          ,
          com.fasterxml.*
          ,
          org.springframework.*
          ,
          org.hibernate.*
          , project packages, etc. (alphabetical inside the block).
        • (blank line)
        • Block 2
          java.*
          and
          javax.*
          (alphabetical). Do NOT split block 1 into per-package sub-blocks. The final file must contain short names in the body (including every Javadoc
          {@link …}
          ) and a clean, grouped import block at the top.
  5. For sub-DTOs (subDtoType=NEW_CLASS): create a separate file by repeating Steps 6.1-6.4 recursively for the sub-entity.
  6. For nested classes (subDtoType=NEW_NESTED_CLASS): add inner class to the parent DTO file, then fill it following the same fragment rules.
  7. Nested in a record parent — MANDATORY: when the parent DTO is a Java record, every
    NEW_NESTED_CLASS
    association MUST be emitted as a nested
    public record
    inside the parent record's body. The skill MUST NOT silently fall back to
    NEW_CLASS
    (separate file) just because the record-form fragment looks shorter. The full procedure is in
    references/java-record.md
    Step 6 and
    examples/_fragments/nested-class/java/nested-class.md
    ("Java record" variant). If those instructions seem ambiguous to you, that is a bug in the skill — fix the docs, do NOT work around it by changing the
    subDtoType
    .

  1. 确定目标路径:
    src/main/{java|kotlin}/{packagePath}/{className}.{java|kt}
  2. 遵循所选参考文件中的生成顺序
  3. 对于每个步骤:
    如果是骨架(新文件):
    • examples/_skeletons/
      读取骨架
      .md
      文件
    • 应用变量替换
    • 使用Write工具创建文件
    如果是片段:
    • examples/_fragments/
      读取片段
      .md
      文件
    • 读取插入点以了解插入位置
    • 使用Edit工具在指定位置插入代码
    • 应用变量替换
  4. 变量替换规则:
    • {packageName}
      → 来自实体包或用户选择
    • {className}
      → 来自用户或默认值
      {EntityName}Dto
    • 字段级变量 → 来自实体详情
    • 绝不替换未在变量列表中列出的内容
    • 绝不添加示例中没有的导入、方法或代码
    • **全限定名处理(重要提示):**示例包含全限定名(例如
      java.util.Objects
      java.util.List
      jakarta.validation.constraints.NotNull
      )。在编写最终文件时,必须:
      1. 将类体中的每个全限定名替换为其短名称(例如
        java.util.Objects.hash(...)
        Objects.hash(...)
        java.util.List<Integer>
        List<Integer>
        @jakarta.validation.constraints.NotNull
        @NotNull
        )。
      2. 收集所有缩短的全限定名,并在
        package
        语句后添加对应的
        import
        行,排序且无重复。
      3. java.lang
        中的类型(
        String
        Integer
        Object
        等)不得导入,必须以短名称显示。
      4. 与DTO同包的类不得导入。
      5. Javadoc
        {@link ...}
        引用——统一规则:对于所有
        类型(顶级Java类、顶级Java record、嵌套静态类、嵌套record、单独文件的子DTO(NEW_CLASS)),生成短名称+导入
        {@link …}
        。不存在不对称情况。始终缩短实体引用,并始终添加对应的
        import
        行(除非实体与DTO同包)。
      6. 分组导入:分为两个块,之间用一个空行分隔:
        • 块1 —— 所有第三方/项目导入:
          jakarta.*
          com.fasterxml.*
          org.springframework.*
          org.hibernate.*
          、项目包等(块内按字母排序)。
        • (空行)
        • 块2 ——
          java.*
          javax.*
          (按字母排序)。 不要将块1拆分为按包的子块。 最终文件的类体中必须使用短名称(包括所有Javadoc
          {@link …}
          ),顶部有清晰的分组导入块。
  5. 对于子DTO(subDtoType=NEW_CLASS):递归重复步骤6.1-6.4,为子实体创建单独文件。
  6. 对于嵌套类(subDtoType=NEW_NESTED_CLASS):将内部类添加到父DTO文件中,然后按照相同的片段规则填充。
  7. **嵌套在record父类中——强制要求:**当父DTO是Java record时,每个
    NEW_NESTED_CLASS
    关联必须作为嵌套
    public record
    在父record的类体中生成。技能不得因为record形式的片段看起来更短就静默回退到
    NEW_CLASS
    (单独文件)。完整流程在
    references/java-record.md
    步骤6和
    examples/_fragments/nested-class/java/nested-class.md
    (“Java record”类型)中。如果这些说明看起来不明确,这是技能文档的bug——修复文档,不要通过更改
    subDtoType
    来规避。

Step 7 -- Mapper (automatic when conversion is needed)

步骤7 —— 映射器(需要转换时自动触发)

Decide whether a mapper is needed based on context, then act:
SignalAction
User said "only DTO" / "no mapper" / "without mapper"Skip Step 7 entirely. Do NOT mention the mapper.
User explicitly asked for a mapper ("and mapper", "with mapper", "create mapper too")Delegate to
mapper-creator
immediately.
From context it is clear that entity↔DTO conversion will happen (user asked to replace entity with DTO in a controller/service/endpoint, user asked to convert/map/transform, DTO is for REST API, etc.)Delegate to
mapper-creator
immediately. The conversion is inevitable — creating the DTO without a mapper would force manual inline mapping code, which is never acceptable.
Context is silent — no signal about how the DTO will be usedSkip Step 7. Do not mention the mapper.
CRITICAL: Never write manual mapping code (inline
toDto
/
fromDto
methods in controllers, services, or anywhere else). If conversion is needed, always delegate to
mapper-creator
. That skill decides the implementation strategy (MapStruct, Custom mapper, adding dependencies) — this skill just delegates.
Never ask
AskUserQuestion
for the mapper. If delegating, invoke the
mapper-creator
skill with the DTO and entity information directly — do not ask the user to confirm the delegation.

根据上下文决定是否需要映射器,然后执行操作:
信号操作
用户说“仅生成DTO”/“不要映射器”/“不带映射器”完全跳过步骤7。不要提及映射器。
用户明确要求生成映射器(“并生成映射器”、“带映射器”、“也创建映射器”)立即委托给
mapper-creator
从上下文可以明确实体↔DTO转换会发生(用户要求在控制器/服务/端点中用DTO替换实体、用户要求转换/映射/变换、DTO用于REST API等)立即委托给
mapper-creator
。转换是不可避免的——创建DTO而不生成映射器会迫使手动编写内联映射代码,这是绝不允许的。
上下文无信号——未说明DTO的用途跳过步骤7。不要提及映射器。
**重要提示:**绝不要手动编写映射代码(控制器、服务或其他地方的内联
toDto
/
fromDto
方法)。如果需要转换,始终委托给
mapper-creator
。该技能会决定实现策略(MapStruct、自定义映射器、添加依赖)——此技能仅负责委托。
绝不要为映射器调用
AskUserQuestion
。如果委托,直接调用
mapper-creator
技能并传入DTO和实体信息——不要询问用户是否确认委托。

Indentation

缩进

The skill MUST detect the project's indentation style — never hardcode tabs or spaces. Detection order:
  1. .editorconfig
    at the project root (or any parent of the target file's directory). For Java files, look up the
    [*.java]
    or
    [*]
    section and read
    indent_style
    (
    tab
    or
    space
    ) and
    indent_size
    /
    tab_width
    .
  2. Sample existing Java files in the same package (or the nearest ancestor package that contains Java files). Detect whether the leading whitespace on indented lines uses
    \t
    or spaces, and how many.
  3. Default to 4-space if neither source is conclusive. (Tabs are also acceptable as a default if the developer explicitly prefers them, but the skill must never silently assume one over the other.)
Whatever style is chosen, apply it uniformly to every line of every generated fragment (fields, constructors, getters/setters, equals/hashCode, toString, nested classes/records). Never mix tabs and spaces inside the same file.
技能必须检测项目的缩进风格——绝不要硬编码制表符或空格。检测顺序:
  1. 项目根目录(或目标文件目录的任何父目录)中的
    .editorconfig
    。对于Java文件,查找
    [*.java]
    [*]
    部分,读取
    indent_style
    tab
    space
    )和
    indent_size
    /
    tab_width
  2. 同一包中的现有Java示例文件(或包含Java文件的最近祖先包)。检测缩进行的前导空格是使用
    \t
    还是空格,以及数量。
  3. 默认回退为4空格如果以上两个来源都无法确定。(如果开发者明确偏好制表符,制表符也可作为默认值,但技能绝不要静默假设其中一种。)
无论选择哪种风格,都要统一应用于每个生成片段的每一行(字段、构造函数、getter/setter、equals/hashCode、toString、嵌套类/record)。同一文件中绝不要混合制表符和空格。

Per-field options

按字段选项

The skill must support the following per-field controls:
  • Field rename (
    fieldNameOverride
    ): the DTO field name can differ from the entity attribute name. Mapper generation still maps it from the original attribute.
  • Add validations (
    extraValidations
    ): the user can add jakarta / hibernate-validator constraints on top of the ones inherited from the entity. The list of allowed constraints depends on the field type — see
    references/validation.md
    .
  • Remove inherited validations (
    removedValidations
    ): the user can drop any constraint that came from the entity field.
  • Edit annotation parameters (
    message
    ,
    min
    ,
    max
    ,
    regexp
    , …): all parameters of every constraint are editable.
These options never appear unless the user explicitly asks for "fine-tune field settings", "per-field validation" or similar. By default the skill just inherits everything from the entity.
技能必须支持以下按字段控制:
  • 字段重命名
    fieldNameOverride
    ):DTO字段名可以与实体属性名不同。映射器生成仍会从原始属性映射到该字段。
  • 添加校验
    extraValidations
    ):用户可以在从实体继承的校验规则之上添加jakarta/hibernate-validator约束。允许的约束列表取决于字段类型——请参阅
    references/validation.md
  • 移除继承的校验
    removedValidations
    ):用户可以移除从实体字段继承的任何约束。
  • 编辑注解参数
    message
    min
    max
    regexp
    等):所有约束的所有参数都可编辑。
这些选项仅在用户明确要求“微调字段设置”、“按字段校验”或类似内容时才会出现。默认情况下,技能仅从实体继承所有内容。

Anti-hallucination checklist

防幻觉检查清单

Before writing ANY code, verify:
  • The code comes from an examples/ file (cite which one)
  • Only declared variables were substituted
  • No framework API calls were added "from knowledge"
  • Import list matches the example exactly
  • Method signatures match the example exactly
  • No comments or convenience methods were added
  • FQNs from examples are shortened in the body AND corresponding
    import
    lines were added after
    package
  • Every Javadoc shape — top-level class, top-level record, nested static class, nested record, separate-file sub-DTO — uses short name
    {@link Pet}
    AND adds a matching
    import
    (unless the entity is in the same package). Uniform rule, no asymmetry.
  • If a sub-DTO name (separate file or nested) would collide with an existing class in the target package, auto-suffix with a number (e.g.
    PetDto1
    ). The skill must do the same — call
    list_existing_classes(package)
    before generating, and append
    1
    ,
    2
    , … until the name is free.
  • When generating a Java record, the inner class for any
    NEW_NESTED_CLASS
    association is also a record (not a static class). All component validators are inlined onto the record component parameters (e.g.
    @NotBlank String firstName
    ), not on separate field declarations.
  • When
    isJavaRecord = true
    , the skill MUST NOT emit
    equals()
    ,
    hashCode()
    ,
    toString()
    , mutable setters, or fluent setters — records auto-generate these and these options should not be available for record DTOs.
  • Class-level Javadoc is multi-line (
    /**\n * DTO for {@link …}\n */
    ), never collapsed to one line.
  • Getters and setters are multi-line (signature line, indented body, closing brace), never one-liners.
  • In
    mutable=true && fluentSetters=false
    mode, getters and setters are interleaved (
    getX, setX, getY, setY, …
    ), not grouped.
  • In
    mutable=true
    mode, both the no-args constructor and the all-args constructor are emitted.
  • The skill does NOT offer "Only ID" as a separate option — this option does not exist (neither for ToOne nor for ToMany). The "association id only" effect is produced by Flat with only the sub-entity
    id
    checked
    , and the skill must implement it that way.
  • For collection associations (
    List<X>
    ,
    Set<X>
    ), Flat is offered and produces composite plural fields (
    Set<Integer> specialtyIds
    ,
    List<Integer> petIds
    ), provided the skill auto-checks the sub-entity scalars.
  • Back-reference
    @ManyToOne
    fields are filtered out of the attribute list (e.g.
    Pet.owner
    is not offered when creating
    PetDto
    ).
  • Imports are grouped with a blank line between
    jakarta.*
    /
    com.*
    /
    org.*
    /
    java.*
    blocks.
  • Indentation matches the project's detected style (
    .editorconfig
    first, then sampling existing files in the same package, then 4-space default). Never hardcode tabs or spaces. Apply uniformly across every fragment in the file.
  • @JsonIgnoreProperties is NOT added for Kotlin (Java-only feature)
  • Validation annotations use
    @field:
    prefix in Kotlin
  • Java types are converted to Kotlin types for Kotlin DTOs
在编写任何代码之前,验证:
  • 代码来自examples/文件(注明具体文件)
  • 仅替换已声明的变量
  • 未添加“凭知识”的框架API调用
  • 导入列表与示例完全匹配
  • 方法签名与示例完全匹配
  • 未添加注释或便利方法
  • 示例中的全限定名在类体中已缩短,且在
    package
    语句后添加了对应的
    import
  • 所有Javadoc类型——顶级类、顶级record、嵌套静态类、嵌套record、单独文件的子DTO——都使用短名称
    {@link Pet}
    并添加匹配的
    import
    (除非实体与DTO同包)。统一规则,无不对称情况。
  • 如果子DTO名称(单独文件或嵌套)与目标包中的现有类冲突,自动添加数字后缀(例如
    PetDto1
    )。技能必须执行此操作——生成前调用
    list_existing_classes(package)
    ,并追加
    1
    2
    ……直到名称可用。
  • 生成Java record时,任何
    NEW_NESTED_CLASS
    关联的内部类也必须是record(而非静态类)。所有组件校验器都内联到record组件参数上(例如
    @NotBlank String firstName
    ),而非单独的字段声明。
  • isJavaRecord = true
    时,技能不得生成
    equals()
    hashCode()
    toString()
    、可变setter或流畅setter——record会自动生成这些,这些选项不应适用于record类型的DTO。
  • 类级Javadoc是多行
    /**\n * DTO for {@link …}\n */
    ),绝不要折叠为单行。
  • Getter和setter是多行(签名行、缩进体、闭合大括号),绝不要写成单行。
  • mutable=true && fluentSetters=false
    模式下,getter和setter是交错排列
    getX, setX, getY, setY, …
    ),而非分组排列。
  • mutable=true
    模式下,同时生成无参构造函数和全参构造函数。
  • 技能不得提供“仅ID”作为单独选项——此选项不存在(无论是一对一还是一对多关联)。“仅关联ID”的效果是通过仅勾选子实体
    id
    的扁平化模式
    实现的,技能必须按此方式实现。
  • 对于集合关联(
    List<X>
    Set<X>
    ),提供扁平化选项并生成复合复数字段(
    Set<Integer> specialtyIds
    List<Integer> petIds
    ),前提是技能自动勾选子实体标量。
  • 反向引用
    @ManyToOne
    字段会从属性列表中过滤掉(例如创建
    PetDto
    时,不提供
    Pet.owner
    )。
  • 导入分组,
    jakarta.*
    /
    com.*
    /
    org.*
    java.*
    块之间用空行分隔。
  • 缩进与项目检测到的风格匹配(优先
    .editorconfig
    ,然后采样同一包中的现有文件,最后默认4空格)。绝不要硬编码制表符或空格。统一应用于文件中的每个片段。
  • 不为Kotlin添加@JsonIgnoreProperties(仅Java特性)
  • Kotlin中的校验注解使用
    @field:
    前缀
  • 为Kotlin DTO将Java类型转换为Kotlin类型