版本更新说明
本文记录 jkit 各版本的用户可见变更。每个版本号只出现一次,按新到旧排列。
未发版的改动追加到当前版本小节(现在是 2.0.1);发版后冻结该小节,在上方新建下一版本。不要改写已冻结的历史版本,也不要为同一版本再开 unreleased 标题。
2.0.1 - 2026-09-13
仓库拆成多模块。本版本随父 POM 一并交付 jkit-sql、jkit-sql-auto(及 Spring Boot 2 / 3 starter)、jkit-notify、jkit-notify-extra、jkit-curl-codegen。坐标 com.alianga:jkit 仍指向 jkit-core。
新增
jkit-sql
- 新模块
com.alianga:jkit-sql:零依赖手写 SQL 解析器(词法char[]+ 关键字开地址哈希,递归下降 AST)。入口SQL.parse/parseAll/parseExpr/format/toSqlString/tables/stat/parameters/parameterize/exportParameterValues/wall/clone/eval/rewrite。非法 SQL 抛SqlParseException。用法见docs/sql.md。 - 方言:一等枚举
MYSQL(默认)、POSTGRES、ORACLE(12c 以下 ROWNUM 分页)、ORACLE12(OFFSET/FETCH)、SQLSERVER、ANSI、H2、DB2、SQLITE、HIVE(别名maxcompute/odps/argo)、CLICKHOUSE、PRESTO(别名trino)、DAMENG(dm/dameng/jdbc:dm:)。fromName覆盖 GoldenDB / SelectDB / AnalyticDB / MatrixOne / StoneDB / HighGo / UXDB / MogDB / Vastbase / AntDB / IvorySQL / GBase 8a / GBase 8s / 行云 / Oscar 等别名,与 icellcommon-model的 SQL 型数据源对齐。能力由SqlDialectSpec驱动,可用SqlDialectWrapper按需覆写单条能力(如 MySQLANSI_QUOTES)。 - 分页:
getLimit/getOffset/setLimit/setOffset/setPage/addLimit/SQL.adaptPagination。format/toSqlString按目标方言适配(MySQLLIMIT↔ 经典 ORACLE ROWNUM ↔ ORACLE12OFFSET FETCH↔ SQL ServerTOP|OFFSET FETCH)。SqlBuilder.limit/offset按有效方言生成,不再一律输出LIMIT。 - 改写链:
SqlRewriteHook+SqlRewrites(addLimit/setPage/andWhere/replaceTable/replaceColumn/adaptPagination/addSelectItem/removeSelectItem可与自定义规则混排)+SQL.rewrite(先深拷贝再改)。跨方言函数改写覆盖 JOIN ON / MERGE / OVER / 列DEFAULT:DATE_ADD/DATEDIFF/FROM_UNIXTIME/UNIX_TIMESTAMP/SUBSTRING/LEFT/RIGHT/DECODE/NVL2/UCASE/LCASE/CONCAT_WS/LPAD/RPAD/YEAR/MONTH/DAY/HOUR/MINUTE/SECOND/SYSDATE/LAST_DAY/CHAR/CHR等;FULLTEXT 升为MANUAL_ACTION_REQUIRED。函数改写走SqlSchemaConverterProvider.registerFunctions(SPI 后覆盖)。 - 实体 DDL:
SqlEntities扫描@SqlTable/ JPA / MyBatis-Plus / MyBatis@Alias(无第三方编译依赖)。公开columnSql/columnTypeSql/createIndex/orderByForeignKeys/extraSql/sequenceSql/indexName/createTable(..., includeIndexes)。认任意简单名为Comment的注解与 Hibernate@ColumnDefault;@SqlTable(comment)/@SqlColumn(comment)按方言生成注释;Oracle ≤11g 无 IDENTITY 时附录 SEQUENCE + TRIGGER。 - 格式化与解析选项:
SqlFormatOptions.keywordCase(AS_IS/UPPER/LOWER)、quoteIdentifiers;SqlParseOptions.pipesAsConcat/keepComments/placeholders()(模板占位符)/statementParsers()(按前导关键字挂自定义语句解析器)。 - 安全与扩展:
SQL.wall→SqlWallResult;SqlWallRule规则链 +SqlWallConfig.rules(...)(内置 selectOnly / denyDdl / 无 WHERE 写等,行为与违规码不变)。SqlAstVisitor类型分发(不破坏SqlVisitorAdapter)。 - 语句 AST:
EXPLAIN/SET/COMMENT ON/SHOW/ANALYZE|VACUUM|OPTIMIZE/ 事务控制 /COPY/FLUSH/START TRANSACTION/LOAD DATA/LOCK TABLES/PREPARE/BEGIN…END/ 过程·触发器·事件(SqlRoutineParam/SqlControlStatement/SqlDeclareStatement/SqlHandlerStatement)升为独立类型;MODEL/MATCH_RECOGNIZE结构化;RENAME TABLE独立语句。 - SqlBuilder:流式 SELECT / INSERT / UPDATE / DELETE,
join/leftJoin/rightJoin/fullJoin/crossJoin/union/with/distinct/groupBy/having。 - 解析覆盖:相对 Druid BVT / JSqlParser 内联 / 文件语料约 96.3% / 92.3% / 90.0%。窗口、CTE、MERGE、PIVOT、闪回、过程块、Hive / ClickHouse / Informix / DB2 等边角语法见
docs/sql.md,不在此按迭代轮次罗列。
jkit-sql-auto
- 新模块
com.alianga:jkit-sql-auto:启动时按实体自动建表 / 更新表结构。扫描@SqlTable/ JPA / MyBatis-Plus,对照DatabaseMetaData执行CREATE TABLE/ALTER TABLE ADD/CREATE INDEX。模式:none/validate/update(默认,只追加)/create/create-drop。配置前缀jkit.sql.auto.*,数据源可回落spring.datasource.*。运行时零第三方依赖。 SqlAuto.drop按外键逆序删托管表;Spring Boot 2 / 3 自动配置模块jkit-sql-auto-spring-boot-2、jkit-sql-auto-spring-boot-3。- 表 / 列注释按方言执行(
COMMENT/COMMENT ON/sp_addextendedproperty);Oracle ≤11g 自增主键用 SEQUENCE + TRIGGER,达梦列上写 IDENTITY。 postgresIdentityStyle/foreignKeys/autoIncrement:给 OpenGauss / GBase 8a / DuckDB 等能力较窄的产品关掉对应 DDL。table-prefix(jkit.sql.auto.table-prefix/ 链式tablePrefix(String)):所有自动建表名统一加前缀(如t_),作用于建表 / 改表 / 删表 / 索引 / 序列 / 外键目标表。index-prefix-enabled(jkit.sql.auto.index-prefix-enabled,默认true):自动派生的索引名是否也带表前缀;实体里显式@Index(name=…)始终原样保留。
jkit-notify
- 新模块
com.alianga:jkit-notify:钉钉(含加签)/ 企微 / 飞书(含签名)/ Server酱 / Bark / 通用 Webhook / SMTP(纯 Socket:AUTH LOGIN + STARTTLS/SSL + MIME)。NotificationChannelSPI +NotificationManager;MessageType(TEXT / MARKDOWN / HTML)。零第三方依赖。用法见docs/notify.md。 - 失败分类:
SendResult.failureType()/isRetryable(),FailureType为 RETRYABLE / THROTTLED / CONFIG_ERROR / PERMANENT / SUPPRESSED;未收录错误码回退 HTTP 状态。自定义渠道覆写AbstractHttpChannel.classify。 - 消息按 UTF-8 字节截断(不劈开汉字与 emoji);钉钉 @人自动把缺失的
@手机号追加进正文;Message.var/vars替换${key}/${a.b};附件流式读取、按10MB/512KB拆包、自动识别 MIME。 - SMTP:
sslProtocols钉扎 TLS 版本、trustAllCerts支持自签网关;MARKDOWN 经NotifyUtils.markdownToHtml按text/html发送。飞书加签写入 JSON 请求体。NotifyPolicy:静默时段、5 分钟去重、本地限流;sendFailover多账号顺序切换。 - 可选模块
com.alianga:jkit-notify-extra:Slack / Telegram / ntfy / 阿里云 / 腾讯云 / 云片 / 华为云短信。渠道 extras 在各自实现类上,不放进核心Message。
jkit-core
DateUtils.parse(String):自动识别时间戳、紧凑数字、-/.、中文/韩文、ISO-8601(含T/Z/+0800/+08:00)。DateUtils.fromEpochNumber(long):10 位秒或 13 位毫秒时间戳转Date。DateUtils.fromTemporal(TemporalAccessor):java.time时间对象转Date。ConvertUtils.toDate额外支持Instant、OffsetDateTime、ZonedDateTime。HttpUtils.debug/HttpUtils.printCurl:发送前把请求摘要或等价 curl 打到标准输出(不要在生产打开)。ConfigLoadOptions.addLocation:在默认搜索路径上追加目录(classpath:/file:/ 裸路径 /File,~展开为user.home)。Print.enableLog:为false时只打控制台,不再写入 JUL。com.alianga.jkit.log.LocaleFormatter:固定 Locale 的 JUL 格式化器。
jkit-curl-codegen
- 从 jkit 拆出独立 artifact
com.alianga:jkit-curl-codegen,入口CurlCodegen.generate(id, curl)。覆盖 34 种目标:Java(jkit / JDK 11+ / OkHttp / Apache 5 / HttpURLConnection / Unirest)、Kotlin、JavaScript(fetch / axios / request / jQuery / XHR 等)、Python(requests / httpx)、Go、C#、PHP、R、Rust、Swift、Ruby、Lua、PowerShell、curl(含 Windows cmd / PowerShell)、wget,以及http/har/httpie互操作格式。
变更
jkit-sql:破坏性 —SQL.andWhere/replaceTable/replaceColumn改为与addLimit/setPage一致的 clone-then-mutate(返回新 AST,不污染原树);调用方须使用返回值。jkit-sql:SQL.clone改为真正的 AST 树拷贝(SqlAstCloner/SqlNode.copy),热路径不再 format→parse;跨方言format/adaptPagination/setPage显著加速。经典 ORACLE offset=0 单层 ROWNUM 包装免 clone。jkit-sql-auto:dryRun(true)的SqlAuto.run(options)/plan(options)不再打开 JDBC / DataSource。URL 仅用于推断方言,按空库规划全量CREATE TABLE。已传入Connection的重载仍对照活表,只是不执行。jkit-core:DateUtils去掉SimpleDateFormat。yyyy-MM-dd HH:mm:ss走char[]+ 秒级缓存,其余常见 pattern 走手写拼接或DateTimeFormatter。ConvertUtils.toDate(Object)改为按数字字段抽取。常见字符串解析约快一个数量级,结果与 ZmlTools 对齐。jkit-core:JUL 默认格式改为英文级别名(WARNING/SEVERE),不再随 JVM 默认语言变化。jkit-core:RandomUtils.randomBirth改为LocalDate(minAge == maxAge不再抛异常);getUUID去-不再走正则;IdCardUtils随机生日按当月实际天数生成。jkit-core:curl 解析对齐 curl 语义(展开-kLs/-XPOST,--json/--data-urlencode,@file不再当字面正文)。公开 API:parseCurl/curlToRequest/curl/curlString/requestToCurl,模型ParsedCurlRequest。CurlParser.generate与http.codegen包从 jkit 移除,改依赖jkit-curl-codegen。jkit-notify:核心ChannelConfig移除 SMS 专用template/appId/region,改用ChannelConfig.extra+AbstractSmsChannel.CFG_*。核心渠道仅由defaults()注册,SPI 只加载 extra 模块,避免双重注册。jkit-notify-extra:SlackChannel.EXTRA_CHANNEL替代用Message.EXTRA_GROUP表示 Slack 频道(短暂回落兼容EXTRA_GROUP)。
修复
jkit-core:响应声明Content-Encoding: gzip但正文为空时,JDK 8 不再抛EOFException,返回空流(关闭时仍回收底层连接)。jkit-sql:子类与MappedSuperclass/ 父类重复声明同名列时只保留子类字段,避免 PostgreSQLcolumn specified more than once。jkit-sql:@GeneratedValue(generator="system-uuid")/GenerationType.UUID/ 非整数@SqlGenerated不再生成AUTO_INCREMENT/IDENTITY(PostgreSQL 对VARCHAR主键写 IDENTITY 会语法错误)。jkit-sql:自动生成的索引名 / 序列名 / 触发器名按方言标识符长度上限截断(经典 Oracle 30 字符,超长时保留前缀 + 4 位散列)。未命名索引改为{table}_{col}_idx,同表多个不再撞名。公开SqlDialectSpec.maxIdentifierLength/fitIdentifier。jkit-sql:SQL.formatpretty 模式对CREATE TABLE按列换行缩进(toSqlString/ compact 仍单行)。jkit-sql:GROUP_CONCAT无显式SEPARATOR时转STRING_AGG/LISTAGG不再丢分隔符;MySQLMODIFY/CHANGE转 PG/ANSI/H2/PRESTO 时不再把列名写重。jkit-sql:SUBSTRING/LEFT/RIGHT按方言回写(PG/MySQL/H2 用FROM n FOR m,SQL Server/SQLite/Hive/ClickHouse 用逗号形态;负起点按LENGTH/LEN改写);达梦裸 SELECT 补FROM dual。jkit-sql:SqlDialectWrapper不再委托派生方法(identQuoteClose/quoteIdent/pipesAreConcat/preferredLimitStyle),子类只覆写原语时派生能力跟着变。jkit-sql:回写保真 —NATURAL JOIN不再丢修饰符;RENAME TABLE不再写成非法ALTER TABLE;ADD UNIQUE KEY不再丢UNIQUE;INSERT/UPDATE/DELETE的IGNORE/LOW_PRIORITY/HIGH_PRIORITY入 AST 并回写;非裸标识符别名强制加引号。jkit-sql:tables()补漏CREATE TRIGGER/CREATE TABLE … LIKE/RENAME TO/ 多表OPTIMIZE|ANALYZE;库名、例程名、CTE 名不再误计。仅注释 / 空白输入归为OTHER,不再抛empty SQL。jkit-sql-auto:经典 Oracle 下自动生成的CREATE INDEX名超过 30 字符时截断,避免 ORA-00972。jkit-curl-codegen:R(httr2)改用req_perform();PowerShell 5.1 受限头 / Cookie 逗号 / 中文乱码;Windows curl 拆成 cmd(shell-curl-windows)与 PowerShell(shell-curl-powershell)两个生成器。
构建
- 仓库改为多模块:父 POM
com.alianga:jkit-parent,运行时库在jkit-core(发布坐标仍是com.alianga:jkit),其余能力各一模块。根目录mvn test同时构建全部模块。 git-commit-id-plugin、buildnumber-maven-plugin、maven-source-plugin从publishprofile 挪到默认构建,package即可产出带构建信息的 sources jar。- 整条 reactor 可用 JDK 8 启动 Maven:其余模块按 JDK 8 编译;
jkit-core的META-INF/versions/9、/11经 toolchain 走 JDK 9 / 11;仅jkit-sql-auto-spring-boot-3经 toolchain 走 JDK 17(Spring Boot 3 要求)。依赖本机~/.m2/toolchains.xml已声明 jdk 8/9/11/17/21。启动示例:JAVA_HOME=$(jdk8) mvn -o clean install。 jkit-notify实发用例须-Djkit.notify.live=true且 yml 凭证齐全;默认mvn test即使有密钥也不实发。
文档
docs/sql.md/docs/en/sql.md按代码对齐跨方言分页、SQL.clone、SqlRewrites、SqlEntities公开方法与方言表;两侧 API 覆盖已对齐。README 与模块 README 去掉内部开发计划入口。docs/sql-auto.md(及英文)按「选包 → 写实体 → Spring Boot / 非 Spring → 配置项」重排;模块 README、快速开始页同步。
2.0.0
jkit 首个对外版本,由 ZmlTools 迁移而来:零第三方依赖、包名改为 com.alianga.jkit,坐标 com.alianga:jkit:2.0.0。
能力概要见 README.md:CSV / HTTP / JSON / YAML / 配置 / 表达式等均用纯 JDK 重写。从 ZmlTools 迁过来的项目可继续用 relocated/zmltools 把 top.wuyongshi:ZmlTools:2.0.0 重定向到本坐标(包名仍需手工替换)。
如何记录后续版本
- 把根
pom.xml(jkit-parent)的<version>改成新版本号,子模块继承该版本;同步README.md页头与依赖示例、Main.java打印的版本。 - 在简介段落后、当前最新版本小节上方插入新版本,日期用当天(
YYYY-MM-DD)。同一版本号只有一个二级标题;未发版前把新条目追加进该小节,不要再开## x.y.z / unreleased。 - 按「新增 / 变更 / 修复 / 构建」分类写清调用方能感知的变化(多模块时用加粗模块名分组)。不要只贴 git 标题,不要按内部里程碑或竞品覆盖率轮次记账(那些写
docs/sql.md/docs/next-plan.md)。 - 本次新增的公开 API 在 javadoc 里补
@since x.y.z。 - 历史版本留在原处,不要把旧条目改写成新版本。
模板:
markdown
## x.y.z - YYYY-MM-DD
### 新增
- ...
### 变更
- ...
### 修复
- ...
### 构建
- ...没有某一类变化时省略对应小标题即可。