# xbatis **Repository Path**: mybatis-mp/xbatis ## Basic Information - **Project Name**: xbatis - **Description**: xbatis是一款基于mybatis的ORM框架;Java 最好的ORM框架 之 ..... - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: https://xbatis.cn - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 15 - **Created**: 2025-12-14 - **Last Updated**: 2025-12-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Xbatis AI Agent 知识库 > 官方站点:https://xbatis.cn > DeepWiki 文档:https://deepwiki.com/xbatis/xbatis # 支持作者,赏作者一盒盒饭(^o^) 面向 AI Agent 的 xbatis 框架知识库,整合官方中文资料中的核心信息,提供自足的说明,帮助自动化助手理解框架能力、常见模式与关键 API。 --- ## 1. 框架总览 - **定位**:xbatis 基于 MyBatis,实现高度 ORM 化的数据库操作体验,强调“少写 SQL、链路化 DSL、跨数据库兼容”。 - **主要优势**: - 多表关联、子查询、链路分页、自动 SQL 优化(自动移除冗余 `LEFT JOIN`、`ORDER BY`,智能 `COUNT` 化简)。 - 内置 `RETURNING` 支持、批量插入与批量更新链路、原生函数包装、SQL 模板。 - 单 Mapper 模式,支持一个 `BasicMapper` 横跨全部实体。 - 多数据库函数库、数据库差异化 `dbAdapt`、动态数据源路由。 - 功能完备的注解生态:逻辑删除、多租户、乐观锁、结果映射、条件映射、动态填充值等。 - **核心特征**(源于框架特点说明): 1. 极致轻量:对 MyBatis 仅做封装而非侵入式改造。 2. 高性能:保持接近手写 SQL 的执行效率。 3. 灵活易用:链式 API 接近自然语言,学习成本低。 4. 高可用:可覆盖超过 90% 常见 SQL 场景。 5. 可靠安全:设计简洁但 API 丰富,稳健通过大量测试。 6. 分页优化:自动优化 `JOIN`、`COUNT`、`ORDER BY`,内置分页器能力。 --- ## 2. 核心模块与包路径 | 模块 | 典型包路径 | 核心类型 | 作用 | |-----------|---------------------------------|---------------------------------------------------------------------------------------------------------------------------|-----------------------------| | 核心 Mapper | `cn.xbatis.core.mybatis.mapper` | `MybatisMapper`, `BasicMapper` | 提供基础 CRUD 与单 Mapper 能力 | | 链式 DSL | `cn.xbatis.core.chain` | `QueryChain`, `InsertChain`, `UpdateChain`, `DeleteChain` | 构建复杂 SQL、批量操作、返回值链路 | | 全局配置 | `cn.xbatis.core.config` | `XbatisGlobalConfig` | 统一配置命名规则、拦截器、动态值、分页等 | | 注解体系 | `cn.xbatis.db.annotations` | `@Table`, `@TableId`, `@TableField`, `@LogicDelete`,`@LogicDeleteTime`, `@TenantId`, `@Version`, `@Condition`, `@Fetch` 等 | 实体映射、注入规则、对象条件、结果加工等 | | 数据库函数 | `db.sql.api.impl.cmd` | `Methods` | 提供跨库函数、SQL 模板、函数链式包装 | | 多租户 | `cn.xbatis.core.tenant` | `TenantContext`, `TenantId` | 全局租户 ID 注册与透传 | | 动态数据源 | `cn.xbatis.datasource.routing` | `@DS`, `JdbcConfigDecryptor` | 运行时切换数据源、加密配置、分组路由 | | 逻辑删除 | `cn.xbatis.core.logic` | `LogicDeleteSwitch`, `LogicDeleteUtil` | 动态开关与便捷关闭逻辑删除 | | 动态值 | `cn.xbatis.core.dynamic` | `XbatisGlobalConfig#setDynamicValue` | 定义 `{NOW}`、`{TODAY}` 等动态填充值 | | 代码生成 | `cn.xbatis.codegen` | `GeneratorConfig` 及子配置 | 一站式生成实体、Mapper、Service 等骨架 | --- ## 3. 快速入门与依赖 ### 3.1 Maven 坐标示例 ```xml cn.xbatis xbatis-bom 1.9.3 pom import cn.xbatis xbatis-spring-boot3-starter ``` ### 3.2 数据源配置示例 ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/dbName username: dbusername password: dbpassword ``` ### 3.3 启动骨架示例 ```java @SpringBootApplication @MapperScan("com.xx.xxx.mapper") public class XbatisApplication { public static void main(String[] args) { SpringApplication.run(XbatisApplication.class, args); } } ``` ### 3.4 Spring Boot 2 集成 - **Maven 依赖**(使用 `xbatis-spring-boot-starter`): ```xml cn.xbatis xbatis-spring-boot-parent 1.9.3 pom import cn.xbatis xbatis-spring-boot-starter ``` - **数据源与 Mapper 扫描**:配置同 3.2/3.3;Spring Boot 2 下可继续使用 `application.yml` 与 `@MapperScan`。 - **启动类**:与 3.3 相同,确保使用 `xbatis-spring-boot-starter` 版本与 Spring Boot 2 兼容。 ### 3.5 Solon 集成 - **Maven 依赖**: ```xml cn.xbatis xbatis-solon-plugin 1.9.3 org.noear mybatis-solon-plugin ${mybatis.solon.version} ``` - **配置示例**: ```yaml # solon.yml ds: schema: demo # 建议与数据库名一致 jdbcUrl: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8 driverClassName: com.mysql.cj.jdbc.Driver username: root password: 123456 # 规则:mybatis.数据源Bean名称 mybatis.master: mappers: - "com.demo.mapper" # 包扫描 - "classpath:mapper/**/*.xml" # XML 扫描 ``` - **数据源 Bean**: ```java @Configuration public class MybatisConfig { @Bean(name = "master", typed = true) public DataSource dataSource(@Inject("${ds}") HikariDataSource ds) { return ds; } } ``` - **业务使用**: ```java @Controller public class DemoController { @Db // 单数据源可省略名称,多数据源需指定 @Db("master") UserMapper mapper; @Get @Mapping("/test") public List test() { return QueryChain.of(mapper) .like(User::getName, "abc") .list(); } } ``` - 更多配置与 `mybatis-solon-plugin` 保持一致,可继续使用链式 DSL、分表、多租户等特性。 实体类、Mapper、Service 的典型写法: ```java @Data @Table public class SysUser { @TableId private Integer id; private String userName; private String password; private Integer roleId; private LocalDateTime createTime; } public interface SysUserMapper extends MybatisMapper {} @Service public class TestService { @Autowired private SysUserMapper sysUserMapper; public Pager demo() { return QueryChain.of(sysUserMapper) .eq(SysUser::getId, 1) .like(SysUser::getUserName, "xxx") .paging(Pager.of(1, 10)); } } > 分页器 `Pager` 位于 `cn.xbatis.core.mybatis.mapper.context.Pager`,实现接口 `cn.xbatis.page.IPager`,常用构造与方法包括: > - 静态工厂:`Pager.of(size)`、`Pager.of(number, size)`。 > - `setExecuteCount(boolean)`:控制是否执行总量统计。 > - `paging(Pager)`:链式 API 传入 `Pager`,结果中可通过 `getResults()`、`getTotal()`、`getNumber()`、`getSize()`、`getTotalPage()` 等方法读取信息。 > - `PagerGetSetUtil` 支持按照 `PagerField` 动态读写扩展字段。 ``` --- ## 4. 全局配置 `XbatisGlobalConfig`(`cn.xbatis.core.config.XbatisGlobalConfig`) - 可在 Spring 启动阶段通过 `ConfigurationCustomizer` 或 `@PostConstruct` 提前设置。 - 常用方法: - `setSingleMapperClass(MybatisBasicMapper.class)`:开启单 Mapper 模式,与 `BasicMapper` 配合。 - `setTableUnderline(boolean)` / `setColumnUnderline(boolean)`:控制表名、列名的下划线策略。 - `setDatabaseCaseRule(DatabaseCaseRule rule)` 或 `setDatabaseCaseRule(DbType, rule)`:设定大小写风格。 - `setDynamicValue("{KEY}", (clazz, type) -> {...})` 与 `getDynamicValue(clazz, type, key)`:挂载并调用动态填充值。 - `setLogicDeleteInterceptor((entity, update) -> {...})` 与 `setLogicDeleteSwitch(boolean)`:统一处理逻辑删除附加字段与开关。 - `addMapperMethodInterceptor(new MyInterceptor())`、`enableInterceptOfficialMapperMethod()`:注册自定义 Mapper 方法拦截器,并可扩展至框架默认方法。 - `setPagingProcessor(DbType, PagingProcessor)`:自定义不同数据库的分页处理。 --- ## 5. 注解体系与属性说明 ### 5.1 `@Table`(`cn.xbatis.db.annotations.Table`) | 属性 | 是否可空 | 默认值 | 说明 | |--------------------|------|----------------------------|-----------------------------------------------------------------| | `value` | 是 | – | 表名,默认按实体名驼峰转下划线,可覆盖 | | `schema` | 是 | – | 指定数据库 schema | | `columnNameRule` | 是 | `columnNameRule.IGNORE` | 定义列名规则,未显式配置列名时按规则生成 | | `databaseCaseRule` | 是 | `DatabaseCaseRule.DEFAULT` | 控制大小写,可结合 `XbatisGlobalConfig.setDatabaseCaseRule(...)` 全局/分库设置 | 示例: ```java @Table(databaseCaseRule = DatabaseCaseRule.UPPERCASE) public class SysUser { } ``` ### 5.2 `@TableId`(`cn.xbatis.db.annotations.TableId`) | 属性 | 是否可空 | 默认值 | 说明 | |-----------------|------|-------------------|--------------------------------------------| | `value` | 是 | `IdAutoType.AUTO` | 主键策略,支持 `AUTO`, `NONE`, `SQL`, `GENERATOR` | | `dbType` | 是 | – | 目标数据库类型,便于多库差异化配置 | | `sql` | 是 | – | `value = SQL` 时必填,自定义取号语句 | | `generatorName` | 是 | – | `value = GENERATOR` 时必填,对应注册的 ID 生成器 | 可重复标注适配多种数据库的主键策略。 ### 5.3 `@TableField`(`cn.xbatis.db.annotations.TableField`) | 属性 | 是否可空 | 默认值 | 说明 | |--------------------------------|------|---------|--------------------------------------| | `value` | 是 | – | 列名,遵循驼峰转下划线可省略 | | `select` | 是 | `true` | `select(Entity.class)` 时是否参与查询 | | `insert` | 是 | `true` | `save` 时是否写入 | | `update` | 是 | `true` | `update` 时是否更新,强制时会更新 | | `neverUpdate` | 是 | `false` | 永不update,除非用UpdateChain指定才会更新,强制也不更新 | | `jdbcType` | 是 | – | 指定 JDBC 类型 | | `typeHandler` | 是 | – | 指定类型处理器 | | `defaultValue` | 是 | – | 插入默认值,支持静态与动态(如 `{NOW}`) | | `updateDefaultValue` | 是 | – | 更新默认值 | | `defaultValueFillAlways` | 是 | `false` | 插入时是否始终填充 `defaultValue` | | `updateDefaultValueFillAlways` | 是 | `false` | 更新时是否始终填充 `updateDefaultValue` | | `exists` | 是 | `true` | 是否真实存在于表中,`false` 可用于非持久化字段 | ### 5.4 `@LogicDelete`(`cn.xbatis.db.annotations.LogicDelete`) 逻辑删除注解 | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `beforeValue` | 是 | – | 删除前的标识值;为空视为 `NULL` | | `afterValue` | 否 | – | 删除后的标识值,可使用动态值 `{NOW}` 等 | 结合 `XbatisGlobalConfig.setLogicDeleteInterceptor` 可额外填充删除人等字段。 #### 5.4.2 `@LogicDeleteTime`(`cn.xbatis.db.annotations.LogicDeleteTime`) 逻辑删除时间字段名,支持 `LocalDateTime`、`Date`、`Long`(毫秒)、`Integer`(秒) ### 5.5 `@TenantId`(`cn.xbatis.db.annotations.TenantId`) 无额外属性。用于标记实体字段为租户 ID,框架在 `save/update/delete` 时自动填充,并在查询条件中追加租户约束。通过 `TenantContext.registerTenantGetter`(`cn.xbatis.core.tenant.TenantContext`)指定租户来源。 ### 5.6 `@Version`(`cn.xbatis.db.annotations.Version`) 无额外属性。标记字段为乐观锁版本,`save` 自动置 0,`update/delete` 自动附加 `WHERE version = ?` 条件。 ### 5.7 生命周期注解:`@OnInsert`(`cn.xbatis.db.annotations.OnInsert`)、`@OnUpdate`(`cn.xbatis.db.annotations.OnUpdate`) | 注解 | 属性 | 是否可空 | 默认值 | 说明 | |-------------|---------|------|-----|-----------------------------------| | `@OnInsert` | `value` | 是 | – | 指定插入前监听器,实现 `OnInsertListener` | | `@OnUpdate` | `value` | 是 | – | 指定更新前监听器,实现 `OnUpdateListener` | 除局部监听外,可通过 `XbatisGlobalConfig.setGlobalOnInsertListener`、`setGlobalOnUpdateListener` 注册全局处理。 ### 5.8 结果映射注解(`@ResultEntity`/`@ResultField`/`@Fetch` 等均位于 `cn.xbatis.db.annotations` 包) - `@ResultEntity`:声明 VO 与实体间的映射关系,自动补充 `SELECT` 列。 - `@ResultField` | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `value` | 是 | – | 可指定一个或多个列名,支持从多个列取值 | | `jdbcType` | 是 | – | 指定 JDBC 类型 | | `typeHandler` | 是 | – | 指定类型处理器 | - `@Fetch` | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `column` | 是 | – | 指定列作为匹配条件;与 `property` 二选一,优先 `column` | | `property` | 否 | – | 源实体属性名 | | `source` | 否 | – | 源实体类型 | | `storey` | 是 | `-1` | 源实体层级,默认自动推断 | | `target` | 否 | – | 目标实体(被拉取的表) | | `targetProperty` | 否 | – | 目标实体关联列 | | `targetSelectProperty` | 是 | – | 指定返回列,可为单列或动态表达式 | | `middle` | 否 | – | 中间实体(中间表) | | `middleSourceProperty` | 否 | – | 中间实体与源实体关联列 | | `middleTargetProperty` | 否 | – | 中间实体与目标实体关联列 | | `orderBy` | 是 | – | 排序字段,支持 `"[{xx} desc]"` 或 `"field desc"` 等写法 | | `multiValueErrorIgnore` | 是 | `false` | 当期望 1 对 1 却返回多条时是否忽略异常 | | `limit` | 是 | `0` | 限制返回条数,0 表示不限制 | | `memoryLimit` | 是 | `false` | 是否在内存中执行 `limit`,配合 `IN` 减少查询次数 | | `nullFillValue` | 是 | `null` | 当结果为空时的填充值 | | `otherConditions` | 是 | – | 额外条件,格式如 `[{Type} = 2]` | - **AI 生成建议**:推荐直接使用 `@ResultEntity` 及其系列注解(`@ResultField`、`@NestedResultEntity`、 `@NestedResultEntityField`、`@ResultCalcField`、`@Fetch`、`@PutEnumValue`、`@PutValue` 等)定义 VO,作为查询结果返回,可省去二次转换逻辑并保持结构稳定。注意这些注解仅适用于 VO/DTO,禁止标注在实体类上;类似的 `@TypeHandler`, `@Put***` 注解也应限定在返回对象中,以避免污染实体模型。 - `@NestedResultEntity`(`cn.xbatis.db.annotations.NestedResultEntity`) | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `target` | 是 | – | 对应的实体类,不填时默认取 `@ResultEntity` 指定的实体 | | `storey` | 是 | `1` | 存储层级;自连接场景用于区分不同层次 | 将 VO 中的字段声明为另一个对象(实体或 VO),框架会自动在查询结果中填充嵌套结构,可继续递归嵌套。 - `@NestedResultEntityField`(`cn.xbatis.db.annotations.NestedResultEntityField`) | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `value` | 是 | – | 指定嵌套实体的字段名 | 当 VO 字段名与实体字段名不同,可在嵌套 VO 上逐字段标注,实现别名映射。常与 Lombok `@FieldNameConstants` 配合避免硬编码。 - `@ResultCalcField`(`cn.xbatis.db.annotations.ResultCalcField`) | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `value` | 否 | – | 计算 SQL,如 `count(1)`、`sum({id})` | | `target` | 是 | – | 对应实体类,缺省继承 `@ResultEntity` | | `storey` | 是 | `1` | 存储层级 | 在 `select(VO.class)` 时自动生成聚合列,无需手写 SQL,动态列请使用 `{字段名}` 占位。 - `@PutEnumValue`(`cn.xbatis.db.annotations.PutEnumValue`) | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `source` | 否 | – | 对应实体类 | | `property` | 否 | – | 实体字段名(枚举编码列) | | `storey` | 是 | `1` | 存储层级 | | `target` | 否 | – | 枚举类 | | `code` | 否 | `code` | 枚举中表示编码的字段名 | | `value` | 否 | `name` | 枚举中表示显示值的字段名 | | `required` | 否 | `false` | 找不到枚举是否报错 | | `defaultValue` | 是 | – | 找不到枚举时的默认值 | 适合“状态码自动转名称”等场景,支持多层嵌套与多列匹配。 - `@PutValue`(`cn.xbatis.db.annotations.PutValue`) | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `source` | 否 | – | 对应实体类 | | `property` | 否 | – | 实体字段名 | | `storey` | 是 | `1` | 存储层级 | | `factory` | 否 | – | 工厂类,需实现指定静态方法 | | `method` | 否 | – | 工厂中提供值的方法名 | | `required` | 否 | `false` | 找不到值是否报错 | | `defaultValue` | 是 | – | 默认值 | 支持基于多个字段注入动态值,方法返回结果会按照 `factory+method+参数` 做 session 级缓存。 上述注解可组合使用:`@ResultEntity` 定义整体映射、`@NestedResultEntity` 构建嵌套结构、`@ResultCalcField` 生成聚合列、 `@PutEnumValue`/`@PutValue` 注入附加信息,从而在 VO 中获得接近实体的自动装配体验。 ### 5.9 分表注解(`@SplitTable`、`@SplitTableKey`、`TableSplitter` 均位于 `cn.xbatis.db.annotations` 包) - `@SplitTable` | 属性 | 是否可空 | 默认值 | 说明 | | --- | --- | --- | --- | | `value` | 否 | – | 指定 `TableSplitter` 实现类,用来根据分表键计算真实表名 | - `@SplitTableKey`:标记实体中的分表字段,仅支持单列,用于在运行时传入分片值。 `TableSplitter` 接口核心方法: ```java boolean support(Class type); String split(String sourceTableName, Object splitValue); ``` `support` 用于声明支持的分片键类型,`split` 根据原始表名和分片值生成真实表名(例如 `sys_user_0`~`sys_user_9` )。查询或更新时需包含分表键条件,框架才能定位具体表。 ### 5.10 条件注解组合 #### `@ConditionTarget`(`cn.xbatis.db.annotations.ConditionTarget`) | 属性 | 是否可空 | 默认值 | 说明 | |---------|------|-------------|-----------------------------------| | `value` | 否 | – | 目标实体类,未指定时默认取当前类 | | `logic` | 是 | `Logic.AND` | 全局默认逻辑,可切换为 `Logic.OR` 实现顶层 OR 组合 | #### `@Condition`(`cn.xbatis.db.annotations.Condition`) | 属性 | 是否可空 | 默认值 | 说明 | |----------------|------|---------------------|------------------------------------------| | `value` | 是 | `Condition.Type.EQ` | 条件类型,如 `LIKE`、`GT`、`BETWEEN`、`EXISTS` 等 | | `target` | 是 | – | 目标实体类,默认继承 `@ConditionTarget` 或当前类 | | `property` | 是 | – | 目标实体属性名,默认与字段同名 | | `storey` | 是 | – | 源实体存储层级,用于嵌套对象 | | `likeMode` | 是 | – | `LEFT`、`RIGHT`、`BOTH` 等模糊匹配模式 | | `toEndDayTime` | 是 | `false` | 当类型为 `LTE` 或 `BETWEEN` 第二个参数时,自动补齐到当天末秒 | | `defaultValue` | 是 | – | 默认值,可为基础类型或动态键(如 `{NOW}`、`{TODAY}`、自定义值) | #### `@Conditions`(`cn.xbatis.db.annotations.Conditions`) | 属性 | 是否可空 | 默认值 | 说明 | |---------|------|------------|-------------------------------| | `value` | 是 | – | 多个 `@Condition` 组合,常用于关键字多列搜索 | | `logic` | 是 | `Logic.OR` | 组合条件间的逻辑运算符 | #### `@ConditionGroup`(`cn.xbatis.db.annotations.ConditionGroup`) | 属性 | 是否可空 | 默认值 | 说明 | |---------|------|-------------|--------------------------| | `value` | 是 | – | 同组字段集合 | | `logic` | 是 | `Logic.AND` | 组内条件的逻辑关系,可改为 `Logic.OR` | DTO 若实现 `ObjectConditionLifeCycle`(`cn.xbatis.core.sql.ObjectConditionLifeCycle`),可在 `beforeBuildCondition()` 中做预处理(如根据 `timeType` 注入近 7 天区间),与上述注解协作构建多层嵌套条件。 --- --- ## 6. Mapper 基础能力 `MybatisMapper`(`cn.xbatis.core.mybatis.mapper.MybatisMapper`)默认提供: - **查询**:`get`, `list`, `listAll`, `listByIds`, `cursor`, `exists`, `count`, `mapWithKey`, `page` 等,可直接接收 Lambda `Where` 闭包。 - **新增**:`save`, `saveOrUpdate`, `saveBatch`, `saveModel`, `saveModelBatch`, `saveBatch(list, fields)` 等,支持实体和 `Model`。 - **更新**:`update`, `updateBatch`, `update(model, where)`, `update(list, forceFields)`, `saveOrUpdate`,并支持指定强制更新字段和批量 `CASE WHEN` 更新。 - **删除**:`deleteById`, `deleteByIds`, `delete(entity)`, `delete(where)`, `deleteAll`,以及 `DeleteChain`。 - **单 Mapper 模式**(适合实体众多、希望统一数据访问层的场景): 1. **用户自己定义 MybatisBasicMapper Mapper 接口和 继承 BasicMapper ** ```java public interface MybatisBasicMapper extends BasicMapper { } ``` `BasicMapper` 位于 `cn.xbatis.core.mybatis.mapper.BasicMapper`,封装所有通用 CRUD。 2. **配置扫描**(Spring Boot 示例) ```java @MapperScan(basePackageClasses = MybatisBasicMapper.class, markerInterface = BasicMapper.class) ``` 这样只生成一个 Mapper Bean,避免为每个实体单独建接口。 3. **注册全局单 Mapper** 在启动阶段执行 `XbatisGlobalConfig.setSingleMapperClass(MybatisBasicMapper.class);`,告知框架以该 Mapper 作为默认入口。 4. **业务层使用方式** ```java @Autowired private MybatisBasicMapper mybatisBasicMapper; public void demo() { // 实体 CRUD mybatisBasicMapper.save(new SysUser()); mybatisBasicMapper.deleteById(SysUser.class, 1); // 链式 DSL:需显式传入实体 Class QueryChain.of(mybatisBasicMapper, SysUser.class) .eq(SysUser::getId, 1) .list(); UpdateChain.of(mybatisBasicMapper, SysUser.class) .set(SysUser::getUserName, "basic") .eq(SysUser::getId, 1) .execute(); } ``` 结合 `BasicDaoImpl`(位于 `cn.xbatis.core.mvc.impl.BasicDaoImpl`)可继续保持三层架构。 5. **处理复杂 SQL** 单 Mapper 仍可配合 XML,通过命名空间 `xxx.MybatisBasicMapper` 与 `withSqlSession` 执行自定义语句: ```java List roles = mybatisBasicMapper.withSqlSession( SysRole.class, "selectByIds", params, (statement, p, sqlSession) -> sqlSession.selectList(statement, p) ); ``` 6. **注意事项** - DSL 需显式提供实体 Class,才能推断表名/字段。 - 若仍需局部自定义 Mapper,可与单 Mapper 并存,但建议统一规范。 - XML 中的 ` select * from sys_role where id >= #{id} and id <= #{id2} order by id asc ``` 调用方式: ```java List roleList = mybatisBasicMapper.withSqlSession( SysRole.class, "selectByIds", params, (statement, p, sqlSession) -> sqlSession.selectList(statement, p) ); ``` - XML 可与链式 DSL 协同使用,按需在链式查询中引用模板或在 XML 中传递动态参数。 --- ## 14. 分页与性能调优 - 内置 `Pager` 对象处理分页:`Pager.of(current, size)`,`QueryChain.paging(pager)` 自动执行分页查询和统计。 - 框架会自动优化分页 SQL:剔除非必要 `LEFT JOIN`、`ORDER BY`,将 `SELECT` 替换为 `COUNT(*)`,提升性能。 - 可通过 `XbatisGlobalConfig.setPagingProcessor` 针对 Oracle、SQL Server 等数据库定制分页语法。 - 自定义分页策略可重写 `customizePager` 接口,例如自定义 count 查询、序列化方式。 - 查询链可指定 `.limit(n)` 控制结果条数,结合 `.forSearch(true)` 对搜索接口做性能优化。 --- ## 15. 代码生成器能力 - `GeneratorConfig` 支持配置实体、Mapper、Mapper XML、DAO、Service、Controller、DTO 等生成选项。 - 可定义包路径、文件后缀、是否生成注解、主键策略、列名映射、数据库类型映射、父类、是否生成 XML 等。 - 支持单 Mapper 模式:`mapperConfig.enable(false).superClass(MybatisBasicMapper.class)`. - 可配置是否生成 `@Mapper` 注解、是否生成泛型、是否生成 `resultMap`、是否输出列信息。 - 支持多语言模板组合,帮助快速搭建项目骨架。 --- ## 16. 启动时安全检查(AI 项目必选) 无论是手工接入还是 AI 自动生成项目骨架,都强烈建议在开发阶段开启 POJO 安全检查:xbatis 会在启动时对 VO(`@ResultEntity` )、Model(实现 `cn.xbatis.core.mvc.Model`)、条件/排序对象(`@ConditionTarget`、`@OrderByTarget`)进行结构校验,提前发现字段映射或注解遗漏。AI Agent 在生成代码时,务必同步生成以下配置,避免遗漏: ```java // 必选:主应用入口启用 POJO 检查 @SpringBootApplication @XbatisPojoCheckScan(basePackages = "com.example.project.pojo") public class ApiApplication { public static void main(String[] args) { SpringApplication.run(ApiApplication.class, args); } } ``` ```java // 推荐:开发环境下的专用配置,可由 AI 自动生成 @Profile("dev") @Configuration @XbatisPojoCheckScan( basePackages = "com.example.api.dto", modelPackages = "com.example.api.model", resultEntityPackages = "com.example.api.vo" ) public class XbatisSafeCheckConfig { } ``` ### 16.1 Spring / Spring Boot - 注解属性说明(`org.mybatis.spring.boot.autoconfigure.XbatisPojoCheckScan`): | 属性名 | 说明 | | --- | --- | | `basePackages` | 基础包扫描路径 | | `modelPackages` | Model 实现所在包,缺省时使用 `basePackages` | | `resultEntityPackages` | VO(`@ResultEntity`)包路径,缺省时使用 `basePackages` | | `conditionTargetPackages` | 条件 DTO(`@ConditionTarget`)包路径 | | `orderByTargetPackages` | 排序 DTO(例如 `@OrderByTarget`)包路径 | ### 16.2 Solon - 在 `solon.yml` 中配置: ```yaml mybatis.master: pojoCheck: basePackages: com.example.**.pojo modelPackages: com.example.**.model resultEntityPackages: com.example.**.vo conditionTargetPackages: com.example.**.condition orderByTargetPackages: com.example.**.orderby mappers: - "com.example.mapper" ``` - `pojoCheck` 配置与 `@XbatisPojoCheckScan` 参数一致,多包路径使用逗号分隔。建议在开发/测试环境开启,以减少生产环境启动耗时。 --- ## 17. 常见排查与实践技巧 - **日志调试**:在日志配置中添加 `` 可打印生成 SQL 与链路信息。 - **忽略空值条件**:`QueryChain` 提供 `.ignoreNullValueInCondition(true)`, `.ignoreEmptyInCondition(true)`, `.trimStringInCondition(true)` 或直接 `.forSearch(true)`. - **安全更新**:`UpdateChain.set` 支持传入函数 `c -> c.plus(1)` 等,用于自增版本或计数字段。 - **批量能力**:通过 `saveBatch`, `updateBatch`, `InsertChain.values` 等高性能批量 API,或 `batchOpt` 模块进一步优化批处理。 - **枚举与字典**:`@PutEnumValue` 可在返回结果中注入枚举文本,`@ResultField` 支持字段级结果映射,`@Fetch` 可自动级联查询。 - **SQL 模板陷阱**:使用模板时若出现单引号问题,可开启封装模式或写双引号。 - **事务下的数据源切换**:跨数据源调用需注意事务传播策略,避免因 Spring 代理导致的数据源无法切换。 --- ## 17. 面向 AI Agent 的实用建议 - **检索策略**:优先考虑 `QueryChain`、`InsertChain`、`UpdateChain`、`DeleteChain` 与注解组合的解决方案,覆盖绝大多数 CRUD 与统计场景。 - **代码生成建议**: - 统一使用方法引用,如 `SysUser::getId`,避免硬编码列名。 - 搜索接口调用 `.forSearch(true)` 或使用带注解的 DTO,以减少手动判断空值。 - 多库场景添加 `dbAdapt`,多租户场景自动带上 `TenantContext`。 - 更新或删除需返回结果时,选择 `.executeAndReturning()` 或 `.executeAndReturningList()`。 - **项目结构建议**: - 单 Mapper 模式适合大型项目,结合 `BasicMapper` 和链式 DSL 统一访问层。 - 动态数据源、租户、逻辑删除等横切特性需在 Agent 生成的代码中显式说明开关状态。 - 通过 `GeneratorConfig` 生成初始骨架,再用 Agent 生成增量链式查询或 Service 逻辑。 - **安全审计**:借助 `@OnInsert`, `@OnUpdate`, 逻辑删除拦截器与租户上下文自动填充创建人、更新时间、租户信息,满足审计需求。 --- ## 附录:开发提效速查(源自 `fast-dev.md`,AI 项目必须考虑) ### 指定数据库类型 为减少自动识别的开销,可在配置中显式声明 `databaseId`: ```yaml mybatis: configuration: databaseId: MYSQL # 参见 db-support.md 获取可用 ID ``` ### 链式 API 的省略写法(AI 代码生成务必采用) - 若查询、`from`、`returnType` 都针对当前 Mapper 的实体类,可省略 `select`/`from`/`returnType`: ```java SysUser user = QueryChain.of(sysUserMapper) .eq(SysUser::getId, 1) .get(); ``` - `select(VO.class)` 与 `returnType(VO.class)` 相同时,可只写 `returnType`,框架会根据 VO 注解自动补全列。 - 批量忽略:`.forSearch(true)` 同时启用忽略 `null`、空字符串并自动 `trim`,AI 默认应启用此策略。 - 精准忽略: ```java QueryChain.of(sysUserMapper) .eq(SysUser::getId, id, Objects::nonNull) .like(SysUser::getUserName, userName, StringUtils::isNotBlank) .get(); ``` ### VO 自动映射 - `@ResultEntity` + `@NestedResultEntity` 可构建任意嵌套结构,字段名与实体一致时可省略注解属性。 - 建议结合 Lombok `@FieldNameConstants`,在注解中引用 `X.Fields.xxx` 避免硬编码。 ### 链路 `connect` 的使用 `connect` 可在链式查询中获取自身句柄,构建复杂子查询: ```java QueryChain.of(sysUserMapper) .select(SysUser::getId, SysUser::getUserName) .connect(query -> query.exists(SubQuery.create() .select1() .from(SysUser.class) .eq(SysUser::getId, query.$(SysUser::getId)) .isNotNull(SysUser::getPassword) .limit(1))) .list(); ``` ### 推荐的数据库函数调用方式 通过静态导入 `db.sql.api.impl.cmd.Methods.*`,让链式代码更简洁: ```java Integer id = QueryChain.of(sysUserMapper) .select(SysUser::getId, c -> sum(add(c, 1))) .returnType(Integer.TYPE) .get(); ``` 这些“省力写法”可极大提升日常开发效率,在构建 AI 生成策略时亦可作为默认建议。 --- 建议将本知识库连同项目源码、依赖 API 文档一起构建为向量知识库,使 AI Agent 能够准确生成符合 xbatis 规范的代码与配置。***