Install
openclaw skills install xbatis-skills在使用 xbatis 的 Java 项目中实现、改写、审查或优化 ORM / Mapper / QueryChain / 联表 / 分页 / VO 映射 / 多租户 / 逻辑删除 / 乐观锁 / SQL 模板相关代码时使用。适用于 Spring Boot 2/3/4、Solon,以及需要让 AI Agent 严格遵循 xbatis 原生风格、优先使用框架能力并控制 XML / 原生 SQL 回退边界的任务。
openclaw skills install xbatis-skills使用这份 Skills 时,优先遵循 xbatis 的原生表达方式,不要把它当成其他 ORM 或传统 XML MyBatis 使用。
处理以下任务时,使用这份 Skill:
BasicMapper、MybatisMapper<T>、QueryChain、UpdateChain、InsertChain、DeleteChain不要将这份 Skill 用于:
始终按以下顺序决策:
始终保持以下优先级:
queryChain() / updateChain() / insertChain() / deleteChain()returnType避免以下默认倾向:
默认按以下项目级约束生成和审查代码:
@XbatisPojoCheckScan 接入;README 记录的包名是 org.mybatis.spring.boot.autoconfigure.XbatisPojoCheckScan,但生成前必须从当前项目依赖或本地 starter 源码确认真实包名solon.yml 的 mybatis.<数据源 bean 名称>.pojoCheck 下配置 basePackages、modelPackages、resultEntityPackages、conditionTargetPackages、orderByTargetPackagesbasePackages 覆盖项目相关包,要么使用 modelPackages / resultEntityPackages / conditionTargetPackages / orderByTargetPackages 等细分包路径;不要同时生成两种方案@FieldNameConstants 支持字段常量引用按任务读取对应参考文件,不要一次性加载全部 references:
@MapperScan 时,读取 references/environment-setup.mdreferences/query-strategy.mdBasicMapper 时,读取 references/mapper-modes.mdreferences/framework-features.mdreferences/advanced-sql.mdreferences/xml-boundaries.mdreferences/review-checklist.md启用 xbatis 任务时,先做这件事:
https://github.com/xbatis/xbatishttps://gitee.com/xbatis/xbatishttps://github.com/xbatis/xbatis-spring-boot-parenthttps://gitee.com/xbatis/xbatis-spring-boot-parenthttps://github.com/xbatis/xbatis-solon-pluginhttps://gitee.com/xbatis/xbatis-solon-plugin先将任务归类为以下一种:
优先使用:
getByIdgetValueByIdBasicDaoImpl<T, ID>DaoImpl<T, ID>避免:
QueryChain优先使用:
queryChain()paging(Pager)避免:
forSearch(true)只有搜索查询、搜索表单、后台筛选页、关键词查询才优先使用 forSearch(true)。
优先使用:
queryChain()@Fetch,不要默认写 join.from(...) 明确主表returnType(VO.class)select(VO.class) 或实体/VO 自动列推导@PutEnumValue避免:
@Fetch 的场景机械改成 joinselect 字段,本可直接 select(VO.class) 却堆大量列优先使用:
updateChain()insertChain()deleteChain()避免:
UpdateChain.of(...)InsertChain.of(...)DeleteChain.of(...)DeleteChain 当成逻辑删除入口优先使用:
最后再考虑:
避免:
落代码前,先确认:
已有明确风格时,跟随项目,不要引入另一套 ORM 写法。
新项目或用户未指定模式时,优先推荐单 Mapper + DAO。
默认执行以下规则:
@Table@TableId@TableField@FieldNameConstants仅在以下场景补更多注解:
推荐的字段规则:
@TableField(defaultValue = "{NOW}", update = false)@TableField(defaultValue = "{NOW}", updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)@TableField("xxx")@TableField@Ignore 或 @Ignores避免:
@TableField默认执行以下规则:
XbatisMapper extends BasicMapperXbatisGlobalConfig.setSingleMapperClass(...)BasicDaoImpl<T, ID>DaoImpl<T, ID>cn.xbatis.core.mvc.Dao<T, ID>setMapper(...) 方法必须加上当前容器框架的自动注入注解;Spring 跟随 @Autowired / @Resource 等项目既有规范,Solon 跟随 @Inject / @Db 等项目既有规范setMapper(...)cn.xbatis.core.mvc.IDao<T, ID>;源码注释说明 IDao 是旧接口且不建议开发者使用避免:
IDao<T, ID>,或不建接口只建实现类重点执行:
references/mapper-modes.mdsetMapper(...),内部调用父类 setMapper(mapper) 完成绑定Dao<T, ID>;业务 DAO 实现类继承项目 BaseDao 并实现该接口setMapper(...)findById、create、modify 这类二次命名@MapperScan 扫描统一 XbatisMapper 所在包;如果项目已使用 markerInterface = BasicMapper.class,延续现有配置XbatisGlobalConfig.setSingleMapperClass(...)默认执行以下规则:
cn.xbatis.core.mybatis.typeHandler.EnumSupport<T>code 值并实现 getCode();字段类型 T 按数据库实际存储类型选择,例如 String、Integer、Longpublic static Xxx of(T code) 方法;遍历枚举按 code 匹配,找不到时返回 nullpublic enum Status implements EnumSupport<Integer> { ... }Enum.name()、ordinal() 或手写 TypeHandler 作为 xbatis 枚举持久化方案@PutEnumValue示例:
public enum Status implements EnumSupport<Integer> {
ENABLED(1),
DISABLED(0);
private final Integer code;
Status(Integer code) {
this.code = code;
}
@Override
public Integer getCode() {
return code;
}
public static Status of(Integer code) {
for (Status item : values()) {
if (java.util.Objects.equals(item.getCode(), code)) {
return item;
}
}
return null;
}
}
生成前必须从本地 xbatis 源码确认真实包名;当前源码中 EnumSupport 位于 cn.xbatis.core.mybatis.typeHandler.EnumSupport。
默认执行以下规则:
queryChain()cn.xbatis.core.mvc.QO 并提供 where()@ConditionTarget、@Condition、@Conditions、@ConditionGroup 等对象转条件注解@Ignore 或 @IgnoresforSearch(true)paging(Pager)@Fetch.from(...) 明确主表leftJoin(SysUser::getRoleId, SysRole::getId) 这类带方法引用的写法,第二个参数所属实体是被 join 的实体select(VO.class);如果 returnType 与 select 类型一致且没有额外 select,可省略 .select(...)按 id 查询:
getByIdgetValueByIdqueryChain()额外检查:
leftJoin 分页优化是否合适,必要时改用 rightJoin() 或关闭 join 优化避免:
@Fetch 的场景机械使用 joinforSearch(true)forSearch(true) 时,仍把值忽略判断散落成外层 if.eq(SysUser::getId, id, Objects::nonNull),却使用更绕的写法or 条件时,没有使用 .nested(chain -> ...)select 字段,本可直接 select(VO.class) 却堆大量列注意:源码接口名是 QO,不要写成 Qo。
注意:QO.where() 中优先使用 WhereUtil.where(this) 写法。
无法使用 forSearch(true),但需要根据值忽略条件时:
.eq(SysUser::getId, id, Objects::nonNull)when 重载,例如 .eq(Objects.nonNull(id), SysUser::getId, id)or 条件时,使用 .nested(chain -> ...)and;调用 .or() 后会持续使用 or,需要切回时显式调用 .and()or 条件优先放进 .nested(...),避免 .or() 状态影响后续外层条件默认执行以下规则:
updateChain()insertChain()deleteChain()UpdateChain、InsertChain、DeleteChain 最终执行方法统一是 execute()save(Model)、update(Model), xbatis 自带这些方法@Ignore 或 @IgnorespartialUpdate(...) 精准修改避免:
UpdateChain.of(...)、InsertChain.of(...)、DeleteChain.of(...)BasicMapper 的 Chain 创建方式partialUpdate(...) 精准修改,却直接对查出的实体做普通 update(entity)UpdateChain、InsertChain、DeleteChain 却没有以 execute() 收尾默认执行以下规则:
@ResultEntity、@NestedResultEntity、@NestedResultEntityField、@ResultCalcField 等结果映射注解@PutEnumValue@Ignore 或 @Ignores避免:
@Table、@TableId、@TableField 等实体类注解将 XML / 原生 SQL 视为后置选项。
仅在以下场景使用:
使用 SQL 模板时:
Methods.tpl(...)Methods.fTpl(...)Methods.cTpl(...)避免在以下场景使用:
优先复用框架逻辑删除能力。
避免:
deleted = 0DeleteChain 删除不触发逻辑删除规则deleteChain()优先使用 @TenantId 和框架多租户能力。
避免:
tenant_id优先使用 @Version。
避免:
优先使用全局动态值、@OnInsert、@OnUpdate。
避免:
实体审计字段建议:
@TableField(defaultValue = "{NOW}", update = false)@TableField(defaultValue = "{NOW}", updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)优先将搜索对象、筛选对象、排序对象交给框架对象转换能力处理。
查询对象规则:
cn.xbatis.core.mvc.QOQO.where() 负责集中构建 Where@ConditionTarget,并按需使用 @Condition、@Conditions、@ConditionGroupQO.where() 中优先使用 WhereUtil.where(this)queryChain(qo.where())Methods 风格时,优先静态导入所需方法,并保持 eq(gt(...)) 这类嵌套表达避免:
iforder by将以下行为视为明显偏离 xbatis 风格:
forSearch(true) 与空值忽略能力forSearch(true)QO 表达的查询条件却散落在 Service 层getById / getValueByIdwhen 重载or 条件时,不使用 .nested(...).or() 后没有显式 .and() 切回,导致后续条件错误变成 OR@TableField("列名")@TableField 的动态默认值能力@ConditionTarget 体系和 WhereUtil.where(this)setMapper(...) 重复写在每个业务 DAO 子类里,而不是在项目 BaseDao 上统一加容器自动注入注解SysUser.Fields.id.as(...) 明明可以使用字段 / getter 引用,却默认回退字符串别名@Ignore 或 @IgnorespartialUpdate(...) 精准修改UpdateChain、InsertChain、DeleteChain 却没有调用 execute()Methods.tpl、Methods.fTpl、Methods.cTpl 创建提交前,逐项检查:
forSearch(true) 是否只用于搜索查询cn.xbatis.core.mvc.QOgetById / getValueByIdwhen 重载or 的成组条件是否使用 .nested(...).or() 后是否已在需要时通过 .and() 切回.from(...)、方法引用 join 和 select(VO.class)@FetchXbatisMapper 并配置 @MapperScan@PutEnumValue@TableField("列名")@TableField(defaultValue = "{NOW}", update = false) 和 @TableField(defaultValue = "{NOW}", updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)@ConditionTarget 体系,并在 where() 中使用 WhereUtil.where(this)setMapper(...) 是否带 Spring、Solon 等容器自动注入注解,业务 DAO 子类是否避免重复重写 setMapper(...)@FieldNameConstants 生成的 Fields.as(...) 是否优先使用 getter / 字段引用形式,例如 .select(SysUser::getId, c -> c.as(SysUser::getId))@Ignore 或 @IgnorespartialUpdate(...) 精准修改UpdateChain、InsertChain、DeleteChain 是否最终使用 execute() 执行Methods.tpl、Methods.fTpl、Methods.cTpl 创建执行:
cn.xbatis.core.mvc.QO@ConditionTarget、@Condition、@Conditions、@ConditionGroup@Ignore 或 @Ignoreswhere() 中优先使用 WhereUtil.where(this)queryChain(qo.where())forSearch(true),其他场景使用对象转条件、predicate / boolean when 或显式条件paging(Pager)执行:
queryChain().from(...) 明确主表,再定义 joinleftJoin(SysUser::getRoleId, SysRole::getId)returnType(VO.class);需要时优先 select(VO.class)@ResultEntity 等结果映射注解;必要时补 @PutEnumValue@Ignore 或 @Ignores执行:
@TableField(defaultValue = "{NOW}", update = false)@TableField(defaultValue = "{NOW}", updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)@OnInsert@OnUpdate始终记住这些规则:
QO 对象转条件并在 DAO 内执行getById,按 id 查单列值用 getValueByIdforSearch(true)@Fetch,真正需要 join 时先 .from(...),再用方法引用 joinQO 并使用 @ConditionTarget 体系;QO.where() 优先用 WhereUtil.where(this)when 重载;成组 or 条件用 .nested(...),.or() 后需要时用 .and() 切回;使用 Methods 风格时优先静态导入select(VO.class) / returnType(VO.class) 自动映射,VO 优先配合 @ResultEntity 等结果映射注解@PutEnumValue@TableField;创建时间优先 @TableField(defaultValue = "{NOW}", update = false),修改时间优先 @TableField(defaultValue = "{NOW}", updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true)@Ignore 或 @Ignores@FieldNameConstants 和 SysUser.Fields.id 这类字段引用.as(...) 优先使用 getter / 字段引用形式,例如 .select(SysUser::getId, c -> c.as(SysUser::getId));只有特殊情况才使用 .as("id")setMapper(...) 上,并补 Spring、Solon 等容器自动注入注解;BaseDao 子类不重复重写 setMapper(...),不默认走构造方法传 MapperpartialUpdate(...) 精准修改UpdateChain、InsertChain、DeleteChain 最终统一通过 execute() 执行Methods.tpl、Methods.fTpl、Methods.cTpl 创建XbatisMapper extends BasicMapper 并配置 @MapperScan,不主动调用 XbatisGlobalConfig.setSingleMapperClass(...)basePackages 和细分包路径中二选一;测试和生产环境不要求默认开启;不知道真实注解包名或配置项时,先查当前 starter 依赖和本地源码如果生成结果不满足这些规则,继续收敛实现方案。