06-为什么是SpringBoot3加JPA加单体按域分包
各位看官,今天黒漂技术佬要跟大伙唠唠一个容易被当成"八股文"、其实暗藏玄机的话题:技术选型。
很多新手一上来就问:为什么不用更潮的 Go?为什么不用更猛的分布式?为什么不上 Kubernetes?为什么是 Spring Boot 3 + JPA + 单体按域分包这么"朴素"的组合?
别急,选型这事儿,跟买车一个道理——你去菜市场买棵白菜,骑个共享单车就够,非得开辆重卡去,那是跟自己过不去。这一篇,我就把这台"车"为什么这么选,给大家掰开揉碎讲明白。
一、先说人话:什么是技术选型
所谓技术选型,就是你这个项目的地基 + 钢筋 + 水泥该用什么。选错了,楼盖到第三层就开始裂;选对了,你后面加十层都不慌。
URM Ultra 这个项目,定位很明确:这是一套面向"可二次开发"的 Demo,把无人售货机、无人车、机械臂三类硬核设备整合进一套后台。它的首要目标不是"上线扛百万 QPS",而是"让你看得懂、改得动、跑得起来"。
记住这句话,下面所有选择都围着它转。
二、为什么是 Spring Boot 3
Spring Boot 是 Java 世界里"约定优于配置"的集大成者。你不用去手写一堆 XML,一个 @SpringBootApplication 注解,再配上 application.yml,服务"嗖"地就起来了。
那为什么偏偏是 3.x 而不是 2.x?这里有几个硬理由:
| 维度 | Spring Boot 2.x | Spring Boot 3.x | 对我们的意义 |
|---|---|---|---|
| Java 基线 | Java 8/11 | Java 17(最低) | 能用 Record、var、密封类等现代语法 |
| Jakarta EE | javax.* | jakarta.* | 包名迁移,跟未来生态对齐 |
| 性能 | 传统 | 更快的启动/更低内存 | Demo 启动快,体验好 |
| 生态寿命 | 进入维护期 | 长期主推 | 学新不学旧,避免刚学就过时 |
| 依赖管理 | 一般 | 更好的 BOM 管理 | 少踩版本冲突的坑 |
小贴士:Java 17 是 Oracle 当前的长期支持版本(LTS),相当于"官方盖章的长期饭票"。选它就对了。
再补一刀:项目用的 spring-boot-starter-parent:3.2.5,这是 3.x 系列里经过充分验证的稳定版。我们没去追最新最野的版本,因为 Demo 求稳,不要求你天天升级。
三、为什么是 JPA(而不是 MyBatis)
这是新手最容易纠结的点。JPA 和 MyBatis 都是干"把 Java 对象存进数据库"这活的,但画风完全不同。
JPA(Java Persistence API) 是一套 ORM(对象关系映射)规范,Spring Data JPA 是它的"傻瓜相机版"——你写个接口方法名,它自动帮你生成 SQL。
MyBatis 则是"手动挡"——你自己在 XML 或注解里把 SQL 一条条写得明明白白。
3.1 JPA 的"免 SQL"魔法
看一段项目源码,你就懂什么叫省心:
// 项目源码:DeviceProductRepository.java
public interface DeviceProductRepository extends JpaRepository<DeviceProduct, Long> {
List<DeviceProduct> findByDeviceId(Long deviceId);
List<DeviceProduct> findByDeviceIdAndSlotNo(Long deviceId, String slotNo);
List<DeviceProduct> findByDeviceIdAndEnabled(Long deviceId, Integer enabled);
}
注意到了吗?这里一个字儿的 SQL 都没有。你只要把方法名按 findBy + 字段名 + 条件 的规矩起好,findByDeviceIdAndSlotNo 就自动等价于:
SELECT * FROM dms_device_product WHERE device_id = ? AND slot_no = ?
Spring Data JPA 在启动时帮你把方法名翻译成 SQL。这对于"先把东西跑起来"的 Demo 来说,简直是救命稻草——你不用先成为 SQL 大师,也能把 CRUD 写完。
3.2 那 MyBatis 就一无是处吗?
当然不是。我得客观,不能一棍子打死。MyBatis 在对 SQL 有极致控制欲的场景很强:复杂多表关联、需要手写优化过的存储过程、DBA 要逐条 review SQL 的强管控团队。它的优势是"所见即所得"。
但代价是:每张表你得写一堆 XML,增删改查各来一遍,样板代码多到让人犯困。
3.3 为什么本项目选 JPA
| 考量点 | JPA(本项目) | MyBatis(对比) |
|---|---|---|
| 上手速度 | 极快,方法名即查询 | 慢,需写 XML/SQL |
| 样板代码 | 极少 | 较多 |
| SQL 掌控力 | 弱(够用) | 强 |
| 与领域模型贴合 | 高(实体即表) | 中 |
| 二次开发友好度 | 高,改字段加方法即可 | 中,改表要同步 XML |
| 学习曲线 | 平缓 | 略陡 |
结论很朴素:Demo 阶段,业务正确性 > SQL 极致优化。等哪天你这项目真要扛高并发复杂报表了,把个别热点查询用原生 SQL 补上也完全来得及(JPA 支持 @Query 写原生 SQL,并不死板)。
黒漂碎碎念:别被"原生才是真男人"的论调带偏。工程上,先跑起来、再谈优化,永远是第一性原理。
四、为什么是"单体 + 按域分包",而不是一上来微服务
这是最有争议的选择,我重点讲。
4.1 微服务不是银弹
新手容易被"微服务"三个字闪瞎眼,觉得不上微服务都不好意思跟人打招呼。但微服务带来的是:服务拆分、注册中心、配置中心、网关、链路追踪、分布式事务……一堆基础设施。
对一套 Demo 来说,这等于为了吃顿火锅,先把整个厨房重盖一遍。
4.2 按域分包:单体里的"微服务预备役"
URM Ultra 用的是单体架构,但内部结构是按业务域(Domain)分包的。看一眼包结构(项目源码):
com.urm.ultra
├── UltraApplication.java # 启动类
├── common/ # 通用响应体、异常、基类
├── config/ # CORS、演示数据初始化
├── product/ # 商品域
├── device/ # 设备/货道/库存域
├── order/ # 订单域
├── payment/ # 支付域
├── vision/ # 视觉识别域
├── vehicle/ # 无人车域
├── robot/ # 机械臂域
├── replenish/ # 补货配送域
├── deviceapi/ # 设备端接入(Agent 控制器)
└── app/ # 小程序消费端接口
每个域内部,又统一是这五层:
| 层 | 职责 | 举个栗子 |
|---|---|---|
| controller | 接收请求、参数校验、返回结果 | AdminProductController |
| service | 业务逻辑、状态流转 | ProductService |
| repository | 数据访问(JPA) | ProductRepository |
| entity | 数据库实体(继承 BaseEntity) | Product |
| dto | 跨层传输对象 | CreateOrderRequest |
4.3 这种结构的好处在哪
好处一:看得懂。 新人进来,想看商品相关逻辑?直奔 product/ 包,所有零件都在那。不用像微服务那样,为了看一个下单流程,开着十个 IDE 窗口到处跳。
好处二:好拆。 这是关键。因为域与域之间只用 service 互相调用(依赖注入),没有跨包的"毛线团"式耦合。将来真要微服务化,把 vehicle/ 整个包搬到一个独立服务里,改改调用方式就行。按域分包就是给未来的微服务打了个桩。
好处三:跑得动。 一个 java -jar,整个系统起来,调试、联调、演示一条龙。设备端、小程序、后台都在一个进程里说话,心智负担最低。
五、和参考项目"同源"这件小事
项目的选型跟参考实现(urm-cloud)技术栈同源:同样是 Spring Boot、JPA、按域分包、admin-api/app-api 分层。
这有什么好处?一是踩过的坑有现成经验可借鉴;二是你学完这套 Demo,去啃参考项目几乎零成本;三是社区里同技术栈的资料、教程一抓一大把,遇到问题好搜。
选型不是标新立异,而是站在成熟实践的肩膀上。对于一个要被很多人"二次开发"的项目,这点尤为致命——你不想别人接手时,满世界找不到一篇能对的上的文档吧?
六、一张表总结选型逻辑
| 选择 | 理由一句话 | 代价/取舍 |
|---|---|---|
| Spring Boot 3.2.5 | 现代、稳定、生态新 | 需 Java 17 |
| Java 17 | LTS 长期支持 | 老库要升级 |
| Spring Data JPA | 免 SQL、开发飞快 | 复杂 SQL 需另写 |
| 单体架构 | Demo 阶段够用、好调试 | 高并发需演进 |
| 按域分包 | 清晰、好拆微服务 | 需自律不越界 |
| H2/MySQL 双源 | 演示零依赖、生产可切 | 见下一篇详述 |
七、黒漂的选型心法
最后送各位一句心法:
“Demo 求清爽,生产求稳妥,选型求同源。”
别为了"看起来厉害"去堆技术。你选的每个组件,都应该能回答一个问题:“它帮我省了什么,又让我付出了什么?” 答不上来,那就是过度设计。
下一篇,我们聊点更"贼"的——H2 内存库如何免安装就能跑,又怎么一键切到 MySQL 生产库。那才是这套 Demo "开箱即跑"的精髓所在。
(本篇完。代码标注"项目源码"处均可对照 urm-server 工程查阅。)

4万+

被折叠的 条评论
为什么被折叠?



