xbatis之springboot启动器
xbatis代码生成器core
xbatis之 solon 容器 启动插件
多数据库路由器 - 又名为多数据源(可以独立于xbatis使用)
基于RuoYi,替换mybatis为xbatis,更强大、更好用、更方便!!!
Official site: https://xbatis.cn
DeepWiki documentation: https://deepwiki.xbatis.cn
A self-contained knowledge pack designed for AI assistants. It summarizes the official Chinese documentation and highlights the essential concepts, usage patterns, and APIs of the Xbatis framework so that agents can generate or maintain projects without additional references.
LEFT JOIN/ORDER BY, smarter COUNT).RETURNING support, batch insert/update DSL, database function wrappers, and SQL templates.BasicMapper.dbAdapt, and dynamic data source routing.| Module | Typical Package | Representative Types | Purpose |
|---|---|---|---|
| Core Mapper | cn.xbatis.core.mybatis.mapper |
MybatisMapper<T>, BasicMapper
|
Provides base CRUD and single-mapper capabilities |
| Fluent DSL |
cn.xbatis.core.chain / cn.xbatis.core.sql.executor.chain
|
QueryChain, InsertChain, UpdateChain, DeleteChain
|
Construct complex SQL, batch operations, returning clauses |
| Global config | cn.xbatis.core.config |
XbatisGlobalConfig |
Centralize naming rules, interceptors, dynamic values, pagination |
| Annotation ecosystem | cn.xbatis.db.annotations |
@Table, @TableId, @TableField, @LogicDelete, @TenantId, @Version, @Condition, @Fetch, etc. |
Entity mapping, data injection, conditional/VO mapping |
| SQL functions | db.sql.api.impl.cmd |
Methods |
Cross-DB function wrappers and templates |
| Multi-tenancy | cn.xbatis.core.tenant |
TenantContext, TenantId
|
Tenant registration and propagation |
| Dynamic datasource | cn.xbatis.datasource.routing |
@DS, JdbcConfigDecryptor
|
Runtime datasource switching, encrypted DS configs |
| Logical delete | cn.xbatis.core.logic |
LogicDeleteSwitch, LogicDeleteUtil
|
Toggle logic-delete behavior, fill delete metadata |
| Dynamic values | cn.xbatis.core.dynamic |
XbatisGlobalConfig#setDynamicValue |
Define tokens like {NOW}, {TODAY}
|
| Code generator | cn.xbatis.codegen |
GeneratorConfig and friends |
Generate entity/mapper/service/controller boilerplate |
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-bom</artifactId>
<version>1.9.2-M1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-spring-boot3-starter</artifactId>
</dependency>
</dependencies>
spring:
datasource:
url: jdbc:mysql://localhost:3306/dbName
username: dbusername
password: dbpassword
@SpringBootApplication
@MapperScan("com.xx.xxx.mapper")
public class XbatisApplication {
public static void main(String[] args) {
SpringApplication.run(XbatisApplication.class, args);
}
}
xbatis-spring-boot-starter):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-spring-boot-parent</artifactId>
<version>1.9.2-M1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-spring-boot-starter</artifactId>
</dependency>
</dependencies>
@MapperScan identical to the general example above.<!-- Important: register Xbatis plugin first, MyBatis plugin second -->
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-solon-plugin</artifactId>
<version>1.9.2-M1</version>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>mybatis-solon-plugin</artifactId>
<version>${mybatis.solon.version}</version>
</dependency>
# 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.master:
mappers:
- "com.demo.mapper"
- "classpath:mapper/**/*.xml"
@Configuration
public class MybatisConfig {
@Bean(name = "master", typed = true)
public DataSource dataSource(@Inject("${ds}") HikariDataSource ds) {
return ds;
}
}
@Controller
public class DemoController {
@Db
UserMapper mapper;
@Get
@Mapping("/test")
public List<User> test() {
return QueryChain.of(mapper)
.like(User::getName, "abc")
.list();
}
}
XbatisGlobalConfig)Configure globally during startup (via ConfigurationCustomizer or @PostConstruct). Notable options:
setSingleMapperClass(MybatisBasicMapper.class): enable single-mapper mode.setTableUnderline(boolean) / setColumnUnderline(boolean): control naming conventions.setDatabaseCaseRule(DatabaseCaseRule rule): define case rules per DB.setDynamicValue("{KEY}", (clazz, type) -> ...): register reusable dynamic placeholders.setLogicDeleteInterceptor(...), setLogicDeleteSwitch(boolean): customize logical delete metadata.addMapperMethodInterceptor(...): register method interceptors.setPagingProcessor(DbType, PagingProcessor): override pagination strategy per DB.@Table
value, schema, columnNameRule, databaseCaseRule.@TableId
AUTO, NONE, SQL, GENERATOR.@TableField
@LogicDelete
@TenantId
@Version
@OnInsert, @OnUpdate
XbatisGlobalConfig.@ResultEntity, @ResultField, @Fetch, ...)@SplitTable, @SplitTableKey, TableSplitter)TableSplitter to resolve real table names.@ConditionTarget, @Condition, @Conditions, @ConditionGroup)ObjectConditionLifeCycle to preprocess inputs.MybatisMapper<T> ships with extensive CRUD APIs:
get, list, listAll, listByIds, cursor, exists, count, mapWithKey, paging, etc.save, saveOrUpdate, saveBatch, saveModel, etc.update, updateBatch, saveOrUpdate, force-update fields, batch CASE WHEN updates.deleteById, deleteByIds, delete(entity), delete(where), deleteAll, truncate, DeleteChain.MybatisBasicMapper and extends BasicMapper interface
public interface MybatisBasicMapper extends BasicMapper {
}
@MapperScan(basePackageClasses = MybatisBasicMapper.class,
markerInterface = BasicMapper.class)
XbatisGlobalConfig.setSingleMapperClass(MybatisBasicMapper.class);
@Autowired
private MybatisBasicMapper basicMapper;
public void demo() {
basicMapper.save(new SysUser());
basicMapper.deleteById(SysUser.class, 1);
QueryChain.of(basicMapper, SysUser.class)
.eq(SysUser::getId, 1)
.list();
}
withSqlSession with the VO/entity Class to execute mapped statements inside BasicMapper namespace.BasicMapper.EntityName:method convention for withSqlSession.save/saveBatch provide .onConflict strategies: ignore or update on duplicates.InsertChain exposes the same onConflict fluent API.QueryChain
select, from, join, where, groupBy, having, orderBy, pagination, nested conditions, subqueries..forSearch() (ignore null/blank & trim), .ignoreNullValueInCondition, etc.get, list, count, exists, paging, cursor, mapWithKey.SysUserRoleVo vo = QueryChain.of(sysUserMapper)
.select(SysUser.class, SysRole.class)
.from(SysUser.class)
.join(SysUser::getRoleId, SysRole::getId)
.eq(SysUser::getId, 1)
.like(SysUser::getUserName, "abc")
.groupBy(SysUser::getId)
.having(SysUser::getId, c -> c.count().gt(0))
.orderBy(SysUser::getId)
.returnType(SysUserRoleVo.class)
.get();
InsertChain
INSERT ... VALUES or INSERT ... SELECT statements in fluent style.UpdateChain
set, arithmetic functions (plus, etc.), RETURNING, nested conditions.DeleteChain
@ConditionTarget, @Condition, @Conditions, @ConditionGroup.ObjectConditionLifeCycle to pre-process request parameters.ORDER BY clauses.db.sql.api.impl.cmd.Methods.* for cross-DB functions (sum, concat, upper, dateAdd, groupConcat, etc.).tpl, fTpl, cTpl for dynamic SQL snippets.QueryChain.of(sysUserMapper)
.select(SysUser::getRoleId, c -> Methods.tpl("count({0})+{1}", c, "1"))
.and(GetterFields.of(SysUser::getId, SysUser::getId),
cs -> Methods.cTpl("{0}+{1}={2}", cs[0], cs[1], 2));
dbAdapt)QueryChain/UpdateChain/DeleteChain/InsertChain.QueryChain.of(sysUserMapper)
.select(SysUser::getId)
.dbAdapt((query, selector) -> selector
.when(DbType.H2, db -> query.eq(SysUser::getId, 3))
.when(DbType.MYSQL, db -> query.eq(SysUser::getId, 2))
.otherwise(db -> query.eq(SysUser::getId, 1)))
.get();
cn.xbatis:xbatis-datasource-routing with @DS to switch datasources.@TenantId and register a supplier via TenantContext.registerTenantGetter.TenantContext returning null.@LogicDelete on entities, fill extra metadata with global interceptors, toggle per-thread using LogicDeleteSwitch.@Version auto-increments versions and enforces safe updates/deletes.@SplitTable and provide a TableSplitter to compute actual table names. Ensure conditions include the shard key.{BLANK}, {NOW}, {TODAY} (with type-specific conversions).XbatisGlobalConfig.setDynamicValue.xxx.MybatisBasicMapper and method IDs follow EntityName:method naming.basicMapper.withSqlSession(entityClass, statementId, params, callback).Pager.of(page, size) and QueryChain.paging(pager).PagingProcessor or customizePager for advanced scenarios..limit, .forSearch(true) to trim heavy queries.GeneratorConfig can generate entities, mapper interfaces, XML, DAO, service, controller, DTO, etc.mapperConfig.enable(false).superClass(MybatisBasicMapper.class)).@SpringBootApplication
@XbatisPojoCheckScan(basePackages = "com.example.project.pojo")
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
@Profile("dev")
@Configuration
@XbatisPojoCheckScan(
basePackages = "com.example.api.dto",
modelPackages = "com.example.api.model",
resultEntityPackages = "com.example.api.vo"
)
public class XbatisSafeCheckConfig {
}
@XbatisPojoCheckScan attributes mirror those in the YAML setup for Solon.<logger name="cn.xbatis" level="trace"/> to inspect generated SQL..forSearch(true) or .ignoreNullValueInCondition(true) to avoid manual null checks.UpdateChain.set accepts lambdas like c -> c.plus(1) for counters.saveBatch, updateBatch, or the dedicated batchOpt module.@PutEnumValue, @ResultField, @Fetch ease conversions.QueryChain, InsertChain, etc.) and annotation-driven DTOs.SysUser::getId) to avoid hard-coded columns..forSearch(true) for search endpoints.dbAdapt is in place; for multi-tenant apps, wire TenantContext automatically..executeAndReturning() / .executeAndReturningList().@OnInsert, @OnUpdate, logic delete interceptors, tenant context).databaseId (e.g., MYSQL) in mybatis.configuration.databaseId to skip auto detection.SysUser user = QueryChain.of(sysUserMapper)
.eq(SysUser::getId, 1)
.get();
@ResultEntity with @NestedResultEntity, and use Lombok @FieldNameConstants to avoid magic strings.connect allows complex subqueries:
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.* for readable expressions (sum, add, etc.).This English edition mirrors the official Chinese documentation so AI agents can build, refactor, and reason about Xbatis-based projects effectively.