欢迎光临
我们一直在努力

Spring JDBC Ultra:一个被遗忘的生态位,正在重新定义持久层框架

Spring JDBC Ultra:一个被遗忘的生态位,正在重新定义持久层框架

引言:持久层框架的“地图”,少了一块

在 Java 持久层框架的版图上,我们熟悉的格局是这样的:

  • ORM(Hibernate/JPA) :以对象为中心,试图把数据库“藏”起来
  • SQL 映射器(MyBatis) :以 XML 为中心,把 SQL 从 Java 里“搬”出去
  • SQL 构建器(JOOQ/QueryDSL) :以类型安全为中心,把 SQL“翻译”成 Java DSL
  • Spring JDBC:以数据库为中心,最薄、最诚实的一层

这张地图看起来挺完整——每种需求似乎都有对应的框架。但细看之下,你会发现中间缺了一大块:一个既保留 SQL 完整表达力、又帮业务开发者省掉重复劳动、还保持 100% 透明可控的生态位。

Spring JDBC Ultra(开源项目名:SimpleDAO)的出现,恰恰填补了这个空白。

它不是“又一个持久层框架”,而是一个全新的生态位。

一、先看清现实:三大主流框架,各有各的死穴

1. ORM(Hibernate/JPA):唯一的收益是单表对象化

ORM 最大的价值在于单表 CRUD 的自动化——session.save(user)、session.get(User.class, id),确实省掉了写 INSERT 和 SELECT 的体力活。

但代价极其沉重:

代价一:SQL 能力被锁死在约 1/3。 标量子查询、派生子查询、半连接、窗口函数——这些在 ORM 的世界里就是“死刑”,你只能退回原生 SQL。

代价二:黑盒程度极高。 缓存机制、代理生成、懒加载、脏检查——每一步都在增加不可控性。

更致命的是,ORM 有一个逃生舱悖论:复杂场景你必须手写 SQL,那“只在简单场景有效的 ORM”还能叫 ORM 吗?它只是一个“单表对象化工具”而已。

2. MyBatis:唯一的收益是 SQL 能力 100%

MyBatis 确实保留了 SQL 的全部表达力——数据库能写的它都能写。

但代价是枷锁极重,且大多无价值:

  • Mapper 接口 + XML 双向绑定,跨文件维护成本极高
  • 上百个属性、几十个标签、十几个注解,你学这些的唯一目的就是为了“能写 SQL”——而“能写 SQL”是 Spring JDBC 本来就有、默认就有的能力
  • 运行时黑盒,你想介入只能靠拦截器——操作 MappedStatement、BoundSql、ParameterHandler 等内部对象,门槛极高
  • 所以才有大量分页插件、数据权限插件——这不是生态繁荣,是补坑生态

你撕开 XML 那层皮,里面到底是什么?不还是一坨低级的字符串拼接吗?Java 里有 replace、format、正则、流式处理,能把字符串玩出花来。XML 有什么?XML 连个像样的循环和字符串截取都写得费劲。

3. Spring JDBC:最诚实,但“裸”到需要自己拼条件

Spring JDBC 面向数据库设计,它把所有精力都放在如何干净、直接、无损耗地执行 SQL 上。它不关心业务长什么样,只关心“你能不能把 SQL 发过去,把结果拿回来”。

但它的问题是:太“裸”了。每次写查询,都要手动写 if (name != null) { sql.append("AND name = ?"); params.add(name); }——大量重复的样板代码。

二、Spring JDBC:最诚实的底座

在深入 Ultra 之前,必须先说清楚一件事:Spring JDBC Ultra 不是要替代 Spring JDBC,它是让 Spring JDBC 更好用。

Spring JDBC 的“诚实”在于它不做任何语义层面的假定——它不知道什么是“单表对象化”,不知道什么是“关系对象化”,它只认 SQL 字符串和参数数组。你给它什么,它就执行什么。它不替你做决定,也不限制你的选择。

Spring JDBC 是“数据库在 Java 世界里的镜子”——它反射的是数据库的原貌,不增不减。

而 Ultra 是在这个“诚实的底座”上,做了一层“面向业务的脚手架”。它不改变 Spring JDBC 的任何行为,它只是在上面搭了一层梯子,让业务开发者能更快、更干净地写出数据访问代码。

三、Spring JDBC Ultra:一个全新的生态位

1. 面向业务设计,而不是面向数据库

这是 Ultra 和其他所有框架最根本的区别。

框架设计视角设计目标抽象对象
Spring JDBC 面向数据库 极简、直接地执行 SQL 关系型数据库的操作接口
Spring JDBC Ultra 面向业务 让业务代码更少、更清晰、更易维护 SQL 语句中动态变化的部分

Spring JDBC 尊敬的是数据库——它把所有精力都放在如何干净地执行 SQL 上。Spring JDBC Ultra 尊敬的是业务——它承认 SQL 结构本身是有规律的,然后针对这个规律做抽象。

Ultra 是“业务需求在 Spring JDBC 上的脚手架”——它不改变 Spring JDBC 的任何行为,只是帮开发者省掉重复劳动。

2. 五大独创特性,构成一个精密咬合的闭环

Ultra 有五个独创特性,它们不是各自独立的“功能堆砌”,而是一个环环相扣的闭环——抽掉任何一个,其他四个的结构性优势都会崩塌。

独创一:四种结果形态(list/row/columns/field)

关系代数无论怎么运算,结果永远逃不出四种形态:多行多列(list)、单行多列(row)、多行单列(columns)、单行单列(field)。Ultra 用四个方法覆盖了数据库查询的所有输出形态。

独创二:BaseCondition 不区分单表联表

WHERE 子句在单表和联表中语义完全一致。Ultra 把这个结构抽出来独立成类,不绑定任何表——同一个条件对象,既可以用在单表查询,也可以用在联表查询。

独创三:不封装关键字、运算符、异常

AND 就是 AND,> 就是 >,数据库抛什么异常就抛什么异常。Ultra 只封装 SQL 的“结构”,绝不封装 SQL 的“语义” 。这是“极致可见性”的底线。

独创四:mergeParams 自动合并多条件参数

在复杂联表场景下,多个条件对象对应多个参数列表。mergeParams 把它们按顺序合并成一个平铺数组,顺序即 SQL 中 ? 出现的顺序——一行代码解决联表参数管理问题。

独创五:永不退居二线的 API

单表是特例,联表是常态。Ultra 不需要为“特例”设计一套 API,再为“常态”设计另一套——因为它在结构层面已经统一了。任何查询场景,都能用同一套 API 覆盖。

3. 业务代码浓度 ≈ 100%

这是一个极其重要的视角:你写的每一行代码,到底是在解决业务问题,还是在伺候框架?

在 MyBatis 里写一个带 5 个条件的查询,你需要:

  • 接口里写方法声明 + 5 个 @Param 注解
  • XML 里写 <mapper namespace>、<select id>、5 个 <if test> 标签
  • 每个条件:3 行 XML(<if> 开标签 + 业务 SQL + </if> 闭标签)

在这 20+ 行代码里,真正表达业务逻辑的只有 5 行 SQL 条件。业务代码浓度 < 30%。

而在 Ultra 里,同样的 5 个条件:

@Override
protected void addCondition() {
and("name LIKE", name, 3); // 业务:按姓名模糊查询
and("age >=", ageMin); // 业务:年龄下限
and("age <=", ageMax); // 业务:年龄上限
add("AND u.name LIKE ?", userName, 3); // 业务:联表用户姓名模糊
add("AND u.dr = 0"); // 业务:过滤已删除
}

5 行代码 = 5 个业务条件,业务代码浓度 100%。

没有接口、没有 XML 头、没有命名空间、没有 OGNL 表达式、没有 @Param 注解、没有 resultMap——没有任何一行代码是“为了伺候框架”而写的。

四、实战印证:从 demo01 到 demo08

Ultra 的 8 个实战案例(simple-dao-demo 项目)覆盖了从单表到复杂联表的全场景:

demo01:单表 CRUD + 审计 + 逻辑删除

@Repository
public class UserDao extends BaseDao<User> {
// 空类,全部 CRUD 能力自动获得
}

继承空类,立即拥有 save、update、delete、findById、list、page 全套方法。

demo02:联表查询 + 分页

private static final String SQL = """
SELECT t.*, u.name user_name, u.phone user_phone
FROM bus_order t LEFT JOIN sys_user u ON t.user_id = u.id
"""
;
public Page<OrderVO> pageJoin(OrderCond cond) {
return page(SQL, cond, OrderVO.class); // 联表分页,一行搞定
}

单表和联表用的是同一套 API——page(SQL, cond, VO.class)。

demo03:条件进阶(IN + 子查询)

add("AND t.age IN ", inAges); // IN 自动展开
add("AND t.id IN (SELECT user_id FROM bus_order WHERE dr=0)", subQuery); // 动态子查询

IN 条件自动展开成 (?,?,?),子查询直接写在字符串里。

demo04:多表联查 + 复杂条件 三表 JOIN,时间范围、模糊查询、IN 条件任意组合,条件传值即生效、不传即忽略。

demo05:报表聚合(GROUP BY + 聚合函数) 同一个 ReportCond 控制多张报表的不同条件组合,SQL 直接写 GROUP BY 和聚合函数。

demo06:mergeParams 多组条件合并

return list(SQL, ReportVo.class, mergeParams(timeCond, bizCond, validCond));

3 个独立条件类分别控制 SQL 中 3 个不同位置,参数一行合并。

demo07:多租户 + 数据权限(AOP 破局)

@Around("@annotation(auth)")
public Object around(ProceedingJoinPoint pjp, DataAuth auth) {
BaseCondition cond = (BaseCondition) pjp.getArgs()[0];
cond.setExtendCondition(" AND " + auth.userField() + " IN (" + userId + ",0)");
return pjp.proceed();
}

Spring AOP + 注解,在 BaseCondition 里动态追加条件——不到 30 行代码解决数据权限。

demo08:字段脱敏 + 审计扩展 Service 层通过 AOP 做字段脱敏,DAO 层完全不知情——横切关注点与持久层彻底解耦。

五、总结:一个被遗忘的生态位

Spring JDBC Ultra 占据的生态位,可以用一张表说清楚:

框架单表对象化关系对象化业务代码浓度SQL 可见性
ORM (Hibernate) ✅ 做得好 ❌ 稀烂 (<1/10) ~40% ❌ 黑盒
MyBatis ⚠️ 靠 Plus ❌ 联表退回 XML ~30% ⚠️ 标签切割
JOOQ ⚠️ 不自动 ✅ 能做 ~50% ⚠️ DSL 翻译
Spring JDBC ❌ 完全手动 ✅ 能做 100% ✅ 100% 透明
Spring JDBC Ultra ✅ 做得最好 ✅ 做得最好 ≈100% ✅ 100% 透明

没有任何一个框架在“单表对象化”和“关系对象化”两个维度上同时做得好。 Ultra 是唯一一个在单表上达到 ORM 级别、在关系查询上达到原生 SQL 级别的框架。

它的核心哲学极其简单:

  • 在“单表 CRUD”这个机械劳动场景:自动化
  • 在“关系查询”这个语义丰富场景:放弃自动化,回到 SQL 本源
  • 在“条件拼接”这个重复劳动场景:用 BaseCondition 抽象
  • 在“扩展”这个横切场景:用 Spring AOP,不挖框架地道

Spring JDBC 面向数据库设计,Ultra 面向业务设计。 前者是“数据库在 Java 世界里的镜子”,后者是“业务需求在 Spring JDBC 上的脚手架”。

这套框架已经在生产环境稳定运行 3 年+,支撑日均百万级请求,服务十余家企业客户。它不是“又一个持久层框架”,它是在 Spring JDBC 这个最诚实的底座上,开辟的一个全新的、被长期忽视的生态位。

相关开源地址

  • 核心框架源码:https://gitee.com/gao_zhenzhong/simple-dao
  • 系统底座:https://gitee.com/gao_zhenzhong/simple-dao-starter
  • 代码生成器:https://gitee.com/gao_zhenzhong/simple-dao-coder
  • 实战案例(demo01~08):https://gitee.com/gao_zhenzhong/simple-dao-demo

  • 删繁就简三秋树,标新立异二月花。 Spring JDBC Ultra 做的不是“又一个框架”,它做的是——去魅。去 MyBatis 之魅、去 ORM 之魅、去复杂性之魅。把 SQL 从 XML 里解救出来,把程序员从框架的盲从里解救出来,把简单从复杂的包装里解救出来。

    赞(0)
    未经允许不得转载:171主机测评 » Spring JDBC Ultra:一个被遗忘的生态位,正在重新定义持久层框架
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址