Bee 3.0.0 LTS 把轻量 ORM 推向了更完整的工程场景:支持多层子表关联查询,分库分表 Sharding 能力同步升级,并增加对虚拟线程的支持。它仍然保持体积小、接口简单和接近 JDBC 的性能特征,3.0.0 LTS 版本体积约为 969K。
对于不想在 Hibernate、MyBatis 与复杂数据访问框架之间反复取舍的团队,这个版本值得从三个角度观察:复杂关系是否更容易表达,分片规则是否能稳定落地,以及虚拟线程是否真的适合当前数据库连接池。
从单表 CRUD 走向多层关联
轻量 ORM 最容易覆盖的是单表增删改查,但真实业务很快会遇到多层关系。例如一个订单包含多个订单项,每个订单项又关联商品、商品分类和库存记录。查询订单列表时,应用通常还希望一次获得这些子对象。
Bee 3.0.0 LTS 的变化重点之一,就是多层子表关联查询。它的价值不只是少写几段 SQL,更重要的是把对象关系和查询结果组织起来,减少手工组装 DTO、重复处理空值以及维护多份映射代码的成本。
不过,多层关联并不意味着所有数据都应该一次性加载。可以按访问场景拆分:
- 列表页只查询订单和必要的摘要字段;
- 详情页再加载订单项、商品和库存;
- 报表场景优先使用明确的投影查询,避免返回完整对象树;
- 对一对多关系设置分页或数量边界,防止笛卡尔积放大结果集。
ORM 能够表达关联,不代表数据库执行计划一定合理。上线前仍应检查生成 SQL、索引命中情况和关联查询的实际行数。
分库分表的关键是同步规则
分库分表功能真正困难的地方通常不在于把表名改成 order_00 或 order_01,而在于所有读写路径必须使用同一套分片规则。
一个可维护的分片策略至少要明确这些问题:
- 分片键是什么,例如
tenant_id、user_id或order_id; - 写入、按主键查询和分页查询是否都能携带分片键;
- 跨分片查询是否被允许,结果如何排序和合并;
- 分片数量变化时,旧数据是否需要迁移;
- 事务边界是否可能跨越多个数据库连接。
3.0.0 LTS 对 Sharding 能力进行同步升级,适合已经使用 Bee 数据访问层、又需要将数据水平拆分的项目。但采用前应把分片配置当作基础设施契约管理,而不是散落在业务代码里的字符串拼接。
下面是一份可以改造的配置示例。配置字段名称需要根据项目实际使用的 Bee Sharding API 调整,这里重点展示分片键、数据源和表规则的组织方式:
sharding:
enabled: true
shard-key: tenant_id
data-sources:
- name: ds_0
jdbc-url: jdbc:mysql://127.0.0.1:3306/app_0
- name: ds_1
jdbc-url: jdbc:mysql://127.0.0.1:3307/app_1
tables:
orders:
actual-data-nodes: ds_${0..1}.orders_${0..15}
database-strategy:
algorithm: tenant_id % 2
table-strategy:
algorithm: order_id % 16
配置完成后,至少要为以下用例编写测试:同一租户写入与读取命中同一数据源、按主键查询命中单表、缺少分片键时能够被明确拒绝,以及跨分片查询的排序和分页结果符合预期。
虚拟线程不是无限连接池
Bee 3.0.0 LTS 支持虚拟线程,这对 JDBC 等阻塞式 I/O 场景尤其有吸引力。虚拟线程可以降低大量等待任务占用平台线程的成本,让传统同步代码在高并发等待场景下拥有更好的资源利用率。
但虚拟线程不会增加数据库服务器能够处理的并发连接数。应用仍然必须正确设置连接池大小、事务范围和慢查询超时。一个常见错误是为每个请求创建虚拟线程,却让每个线程都长期占用一个数据库连接,最终瓶颈仍然出现在连接池或数据库端。
下面的程序可以直接用 JDK 21 编译运行,验证虚拟线程的基本执行方式:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class VirtualThreadDemo {
public static void main(String[] args) throws InterruptedException {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000; i++) {
int taskId = i;
executor.submit(() -> {
Thread.sleep(10);
System.out.println("task=" + taskId
+ ", virtual=" + Thread.currentThread().isVirtual());
return null;
});
}
}
System.out.println("all tasks completed");
}
}
运行命令:
javac --release 21 VirtualThreadDemo.java
java VirtualThreadDemo
将它接入 Bee 应用时,可以让请求任务运行在虚拟线程执行器中,同时继续使用有上限的 JDBC 连接池。压测时重点观察连接池等待时间、数据库 CPU、事务持续时间和 P99 延迟,而不是只看虚拟线程数量。
小体积带来的工程取舍
Bee 3.0.0 LTS 约 969K 的体积适合对启动速度、依赖数量或部署包大小敏感的服务,也适合 Android、鸿蒙等资源受限场景。它同时覆盖 ORM、Sharding、MongoDB ORM 等使用方向,定位上更像一个小巧的应用数据访问层。
轻量并不等于没有边界。团队需要确认以下事项:
- 当前项目使用的数据库和驱动是否经过完整验证;
- 复杂查询是否可以查看并审计最终 SQL;
- 多层关联是否支持项目需要的分页、排序和懒加载策略;
- Sharding 场景下的事务、跨分片聚合和数据迁移如何处理;
- 虚拟线程与连接池、监控系统及上下文传递是否兼容。
采用建议
升级到 Bee 3.0.0 LTS 可以从一个边界清晰的服务开始:先验证普通 CRUD 和原生分页,再验证一组真实的多层关联查询,随后在测试环境接入分片规则,最后使用 JDK 21 对虚拟线程进行压测。
判断升级是否成功,不应只看依赖体积或吞吐量。更可靠的标准是:查询代码是否更容易维护,生成 SQL 是否可控,分片命中是否稳定,数据库连接是否没有成为新的瓶颈。满足这些条件后,Bee 3.0.0 LTS 才真正适合进入生产环境。