7
数据库方言支持
4
核心元数据 API
1 步
数据源切换
0 行
手写 SQL / Mapper
1
整体架构:AnyLine 驱动全链路代码生成
多数据源 → 元数据解析 → 动态建表 → 代码生成,四步闭环
| 源文件 | AnyLine 使用方式 | 核心价值 |
|---|---|---|
| DsTypeEnum | 定义 7 种数据库的 AnyLine Adapter 全类名 | 运行时检测方言插件是否已加载 |
| AnylineDataSourceHelper | DataSourceHolder.reg() 按需注册数据源到 AnyLine | 统一封装数据源上下文切换,finally 中自动清理 |
| CreateTableHandler | service.ddl().create(table) / service.ddl().drop(table) | 可视化配置 → 自动执行 CREATE TABLE,全程零 SQL |
| GenTableServiceImpl | metadata().tables() / metadata().columns() / queryTableDdl() | 逆向解析任意数据源表结构,生成 DDL 和字段信息 |
| GenDatasourceConfServiceImpl | ClassUtil.loadClass(adapterClassName) 检测方言 | 判断 pom.xml 中是否引入某数据库的 AnyLine 适配器 |
2
核心能力一:7 大数据库方言零缝适配
DsTypeEnum:数据库类型 + JDBC URL 模板 + AnyLine Adapter 全类名,一行定义
🐬
MySQL
MySQLAdapter
🐘
PostgreSQL
PostgresqlAdapter
📋
SQL Server
MSSQLAdapter
🔶
Oracle
OracleAdapter
🟦
DB2
DB2Adapter
国产
🟩
达梦 DM
DMAdapter
国产
🦅
HighGo 人大金仓
HighgoAdapter
⚙️
新增数据库
只需在枚举加一行
// DsTypeEnum.java — 一行定义一种数据库的完整配置
public enum
DsTypeEnum {
// MySQL
MYSQL("mysql", "jdbc:mysql://%s:%s/%s...", "select 1",
"mysql8 链接", "org.anyline.data.jdbc.mysql.MySQLAdapter"),
// 达梦(国产)
DM("dm", "jdbc:dm://%s:%s/%s", "select 1 from dual",
"达梦连接", "org.anyline.data.jdbc.dm.DMAdapter");
// 切换数据库:只需修改 pom.xml 依赖,业务代码零改动
// GenDatasourceConfServiceImpl.listParserPlugins() — 检测方言适配器是否已加载
Map<String, Boolean> result = new LinkedHashMap<>();
for (DsTypeEnum dsEnum : DsTypeEnum.values()) {
result.put(dsEnum.getDbName(),
isClassPresent(dsEnum.getAnylineAdapter()));
}
// 返回 {"mysql": true, "dm": false, "oracle": true, ...} — 告诉用户缺少哪个适配器
3
核心能力二:AnylineDataSourceHelper 数据源上下文封装
三件事,一次封装,全部搞定
业务层只需要关注具体操作逻辑,不再重复处理数据源切换细节
🔍
获取动态数据源
从 DynamicRoutingDataSource 中按名称取出
📋
向 AnyLine 注册
DataSourceHolder.reg() 按需注册,避免重复
🧹
切换 & 清理上下文
DynamicDataSourceContextHolder.push() → finally clear()
无返回值 AnylineDataSourceHelper.run(dsName, action)
// 最常用写法:切换数据源 + 执行 + 自动清理
AnylineDataSourceHelper.run(dsName, () -> {
createTableService.createTable(vo);
// AnyLine 在后台自动切换到 dsName 对应的数据源
});
有返回值 AnylineDataSourceHelper.execute(dsName, supplier)
// 带返回值:元数据查询、表同步等场景
GenTable table =
AnylineDataSourceHelper.execute(dsName, () -> {
Table meta =
ServiceProxy.service().metadata().table(name);
return buildGenTable(meta);
});
核心逻辑 registerIfAbsent — 按需注册,防止重复
// 关键:已注册则跳过,未注册才注册
private void registerIfAbsent(String dsName, DataSource ds) {
if (DataSourceHolder.exists(dsName)) {
return;
}
DataSourceHolder.reg(dsName, ds);
}
4
核心能力三:跨数据源元数据解析
GenTableServiceImpl — 三类元数据 API,零 SQL 实现表结构逆向
API 1 queryTableDdl — 逆向生成建表 DDL
// 输入表名 → 输出 DDL 语句,全程 AnyLine 自动生成 SQL
public String queryTableDdl(String dsName, String tableName) {
DynamicDataSourceContextHolder.push(dsName);
Table table = ServiceProxy.metadata().table(tableName);
table.execute(false); // 不执行,只生成 SQL
ServiceProxy.ddl().create(table);
return table.getDdl(); // MySQL 返回 CREATE TABLE ...
}
API 2 queryTableColumn — 解析表的所有字段元数据
// 一次性获取表的所有列:字段名、类型、注释、主键、自增
public List<Column> queryTableColumn(String dsName, String tableName) {
DynamicDataSourceContextHolder.push(dsName);
CacheProxy.clear(); // 清除缓存,保证最新
return ServiceProxy.metadata().columns(tableName).values()
.stream().toList();
}
API 3 queryTablePage — 分页浏览数据源下的所有表
// 按表名/注释模糊搜索,按创建时间倒序,支持分页
public IPage<Table> queryTablePage(Page page, GenTable table) {
DynamicDataSourceContextHolder.push(table.getDsName());
CacheProxy.clear();
List<Table> list = ServiceProxy.metadata().tables()
.values().stream()
.filter(t -> StrUtil.containsIgnoreCase(...))
.sorted(...).toList();
return CollUtil.page(..., list);
}
5
核心能力四:可视化配置驱动动态建表
CreateTableHandler — UI 配置字段 → AnyLine DDL 执行,全程零手写 SQL
// CreateTableHandler.createTable — 核心逻辑
public Boolean createTable(String dsName, TableInfo tableInfo) {
AnylineService service = ServiceProxy.service(dsName);
// 检查表是否已存在,已存在则删除后重建
Table table = service.metadata().table(tableInfo.getName(), false);
if (null != table) service.ddl().drop(table);
// 执 行建表:AnyLine 根据数据源类型自动生成方言 SQL
service.ddl().create(tableInfo);
return true;
}
// CreateTableServiceImpl — 前端 VO → AnyLine Column 模型
private Column buildColumn(GenCreateTableColumnVO col) {
Column column = new Column();
column.setName(col.getName());
column.setType(col.getType());
column.setComment(col.getComment());
column.setLength(col.getLength());
column.setPrimary(col.getPrimary());
column.setAutoIncrement(col.getAutoIncrement());
return column;
}
// GenCreateTableController.save() — 控制器调用封装
@PostMapping
public R save(@RequestBody GenCreateTableVO vo) {
AnylineDataSourceHelper.run(vo.getDsName(),
() -> createTableService.createTable(vo));
return R.ok(createTableService.saveOrUpdate(genTable));
}
6
MyBatis × AnyLine:动静互补的代码生成架构
•
GenTable — 代码生成的表配置
•
GenTableColumn — 字段配置
•
GenDatasourceConf — 数据源连接配置
•
GenCreateTable — 动态建表记录
编译时结构已知,ServiceImpl 标准 CRUD
•
ServiceProxy.metadata() — 跨数据源查表/列
•
ddl().create() / ddl().drop() — 动态建表/删表
•
DataSourceHolder — 动态数据源注册
•
AnylineDataSourceHelper — 上下文封装
运行时结构未知,AnyLine 统一处理
7
案例总结
AnyLine 在 pig4cloud codegen 中的定位
多数据源代码生成的数据库抽象层
🌐
多数据源元数据
metadata() 统一抽象
🗄️
DDL 方言适配
create/drop 自动方言转换
🔌
动态数据源注册
DataSourceHolder 热插拔
🔍
方言插件检测
isClassPresent 运行时判断
💡 AnyLine 价值
验证"元数据驱动"核心定位:pig4cloud codegen 将 AnyLine 的元数据能力发挥到极致——连接任意数据库,自动解析表结构、字段、主键、自增、注释,生成完整 CRUD 代码,全程零 SQL。
国产数据库适配的标杆场景:达梦 DM 和 HighGo 人大金仓通过 AnyLine 统一接入,无需为每种数据库写定制代码,一套逻辑覆盖全部。
🎯 可复制的技术路径
代码生成器的标准数据层范式:AnyLine metadata() + MyBatis 双引擎是所有代码生成器的最优数据层架构,MyBatis 管配置,AnyLine 管目标数据库。
数据源管理层封装模板:AnylineDataSourceHelper 是多数据源环境下 AnyLine 集成的最佳实践封装,registerIfAbsent + push + finally clear 三步标准化。
源码分析来源
• DsTypeEnum.java — 7 种数据库类型定义,含 AnyLine Adapter 全类名
• GenTableServiceImpl.java — metadata() 元数据解析(tables / columns / DDL 逆向)
• GenDatasourceConfServiceImpl.java — 动态数据源 CRUD + 方言插件检测
• GenCreateTableController.java — 可视化建表接口(AnylineDataSourceHelper.run)
• GenDsConfController.java — 数据源管理接口 + 文档生成
• CreateTableServiceImpl.java — 前端 VO → AnyLine Column 模型构建
• CreateTableHandler.java — ddl().create() / ddl().drop() 动态建表核心逻辑
• AnylineDataSourceHelper.java — 数据源上下文统一封装