网易首页 > 网易号 > 正文 申请入驻

方法名像Spring Data,编译后却没有运行时扫描

0
分享至

看到 findFirstByDriverAndStateIn 这样的方法名,用过 Spring Data 的人立刻能猜到它要查什么。Codename One 把这套仓库模型搬到了客户端和后端,但走的是另一条路:构建时生成具体实现,再直接编译进原生可执行文件。


Codename One 是一个开源框架,用同一份 Java 或 Kotlin 代码构建原生 iOS、Android、桌面和 Web 应用。它这次带来的仓库接口,写法眼熟,运行方式却完全不同。

差别在于运行时那套准备工作被拿掉了。构建阶段生成仓库的具体实现,原生打包时提前编译,启动时不需要扫描类去找仓库,也不需要生成代理。直接调用还让编译器拿到了可分析和优化的代码。

本周的 Wayline 应用把仓库用在了网约车服务上。与之配套的还有 Spring 风格的事务隔离和完成回调,用来控制系统的其他部分何时能对一次数据库变更做出反应。

查询写在找得到的地方

Wayline 的仓库接口直接声明自己要读什么。下面这段来自 RideRepository 的简化接口:

  • 接口标注 @Repository,指定实体为 Ride、键类型为 String;
  • 继承 CrudRepository;
  • 声明 findFirstByRiderAndStateIn 和 findFirstByDriverAndStateIn 两个方法。

实现由构建生成,直接调用会话,不在运行时扫描类来发现仓库。没有 Hibernate 依赖,也没有运行时代理生成。同一套仓库 API 在客户端 ORM 会话和后端会话上都能用。

Spring Data 用户会认出这套命名约定,Hibernate 用户会认出托管实体和脏检查。这些约定在 Codename One 自己的包下受支持,API 边界是有意收窄的。方法名看着眼熟,不等于现有的 Spring 或 Hibernate 依赖就能直接搬过来。

继承来的方法包括 insert、save、findById、findAll、count、existsById 和 deleteById。有两个细节要记住:findById 找不到时返回 null;save 返回的是 merge 产生的托管对象,如果还要继续修改它,请保留这个返回值。

静态编译把准备工作做一次

仓库接口在构建期间变成具体实现。借助 ParparVM,这份 Java 实现和应用的其余部分一起进入原生二进制。没有反射式的仓库分发,也没有需要初始化的运行时实现工厂。

这省掉的是启动和分发仓库调用上的开销,数据库查询本身的成本并没有消失:索引、往返次数、行数依然重要。CASE 聚合和分页能把这类工作留在数据库里,避免加载不必要的实体。

方法名长,不一定就是最清晰的查询。派生查询支持比较、And/Or、显式排序和限制结果数。给列表查询加上 PageRequest(offset, size),就能拿到一页数据,而不必额外发一次总数查询。排序里要带上唯一的决胜字段,否则分数相同的行会在分页之间来回漂移。

条件聚合则把查询写出来。下面这个简化例子用到了指南里的 RepositoryRecord 实体,它有一个数值字段 score:

@Query("select sum(case when r.score >= :floor then 1 else 0 end) " + "from com.codenameone.developerguide.snippets.repository.RepositoryRecord r")
Long qualified(@Param("floor") long floor);

CASE 表达式让数据库去数符合条件的行,而不是让应用把它们全取回来。命名值以绑定参数传入。原生 SQL 查询同样可用,只是标量结果 API 更窄,还要承担所选 SQL 的可移植性代价。

仓库参考文档写明了语法。不支持的方法签名会在生成阶段失败。JPQL 语法和映射名在方法创建查询时、SQL 执行之前接受检查。这个区别值得留意:它并不承诺所有查询错误都会变成编译错误。

事务留在服务层

仓库不开启也不提交事务,边界由服务持有。下面是 Wayline 实际的读取路径:

@Transactional(readOnly = true)
public RideDto activeForRider(String rider) throws IOException {
Ride ride = rides.findFirstByRiderAndStateIn(rider, ACTIVE);
return ride == null ? none() : toDto(ride, rider, new HashMap());
}

这段代码位于 Rides 中,旁边是它的仓库和映射辅助方法。要改动多个实体的方法,会用一个事务包住整个工作单元。仓库的会话参与其中,因此修改托管实体后,事务完成时可以刷写出去。

批量操作需要单独对待。派生删除和声明的修改型查询会先刷写待处理变更,执行批量 SQL,再清空持久化上下文。它们绕过逐实体回调和级联。继续操作前要重新加载对象,手里留着的引用仍然装着旧的 Java 值。

在外层边界选择隔离级别

注解现在可以接受隔离级别:

@Transactional(isolation = Isolation.SERIALIZABLE)

这是一段注解摘录,放在启动整个工作的那个方法上。它请求一个该级别的物理事务,不会悄悄升级已经存在的外层事务。

加入的作用域如果请求了显式级别,必须与外层作用域的显式级别一致。加入 DEFAULT 作用域却提出显式请求,会失败。要么在开始时选好级别,要么在操作确实需要独立事务和连接时使用 REQUIRES_NEW。

数据库点头之后再通知

在线程绑定的事务内部,可以注册 Transactions.Synchronization。下面是指南给出的回调形态,注释标出了应用逻辑该放的位置:

  • beforeCommit:在 ORM 刷写和提交之前做校验;
  • afterCommit:让缓存失效或安排事件;
  • afterCompletion:按 COMMITTED、ROLLED_BACK 或 UNKNOWN 释放资源。

afterCommit 执行时,连接已经回到池里。要做更多数据库操作,得开一个新事务。如果回调失败,原来的数据库变更仍然已提交,调用方会收到说明这一点的异常。盲目重试整个操作,可能把工作做两遍。

这些回调是同步的、在内存里的,不能让事件投递在进程崩溃后依然可靠。对于必须最终送达的消息,在原始事务里写一条 outbox 记录,再单独投递。

Wayline 目前用一个事务性私有方法加随后的通知代码来表达类似的顺序。编译器把事务处理写进方法里,所以通过 this 调用也绕不过去。完成钩子则给其他服务提供了一个明确的位置,安放提交之后的工作。

仓库、CASE 表达式、隔离级别和回调是几项独立的补充,放在一起更有用:查询的管道代码少了,重要的顺序依然看得见。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
人口告别世界第一?催生“二孩”无效后,国家终于向住房出手了!

人口告别世界第一?催生“二孩”无效后,国家终于向住房出手了!

混沌录
2026-05-30 23:41:14
普京把话说绝了:在完全占领乌克兰领土之前,不会签署停战协议

普京把话说绝了:在完全占领乌克兰领土之前,不会签署停战协议

云上乌托邦
2026-10-23 15:06:22
蓉城真要丢冠?末轮打平泰山仍夺冠!英博想逆转必须同时满足2条件

蓉城真要丢冠?末轮打平泰山仍夺冠!英博想逆转必须同时满足2条件

念洲
2026-10-24 17:31:48
金鸡提名爆冷!装疯卖傻、大脑空空,难怪金鸡奖从不提名流量明星

金鸡提名爆冷!装疯卖傻、大脑空空,难怪金鸡奖从不提名流量明星

林轻吟
2026-10-23 07:20:14
中国面临两大战略缺口:一个是“台湾”问题,另一个曾动用300万大军才勉强堵住的致命防线

中国面临两大战略缺口:一个是“台湾”问题,另一个曾动用300万大军才勉强堵住的致命防线

林杰论事
2026-10-18 15:37:07
深圳宝安沙井工业园辅道停满“落灰车”!300米17台开不到50公里的梦想座驾

深圳宝安沙井工业园辅道停满“落灰车”!300米17台开不到50公里的梦想座驾

华庭讲美食
2026-10-24 14:29:36
墨西哥美女格斗选手赛场意外走光7秒,却因此在成人平台上被打赏超过50万刀?!

墨西哥美女格斗选手赛场意外走光7秒,却因此在成人平台上被打赏超过50万刀?!

油了个管
2026-10-24 09:00:28
菲律宾2架飞机相撞,机上人员全部遇难

菲律宾2架飞机相撞,机上人员全部遇难

封面新闻
2026-10-24 17:20:05
医院大检查,上百个药被点名

医院大检查,上百个药被点名

赛柏蓝
2026-10-24 18:53:34
“浑身都是放纵的痕迹!”母亲晒儿子大学三年变化,连面相都变了,家长认为责任在学校,网友们痛斥

“浑身都是放纵的痕迹!”母亲晒儿子大学三年变化,连面相都变了,家长认为责任在学校,网友们痛斥

蝴蝶花雨话教育
2026-10-20 00:05:15
跟监赖清德长子?华裔女子出庭不认罪,最重将被关15年

跟监赖清德长子?华裔女子出庭不认罪,最重将被关15年

金牛传声
2026-10-24 20:48:34
没人喂饼原形毕露!2米26大中锋仅5分2板,球迷:杜锋真没骂错你

没人喂饼原形毕露!2米26大中锋仅5分2板,球迷:杜锋真没骂错你

弄月公子
2026-10-24 08:53:18
世界空手道联合会致信乌莎:被停职裁判为何随印度队出征

世界空手道联合会致信乌莎:被停职裁判为何随印度队出征

日常碎碎念啊
2026-10-24 01:46:04
被停职审查、套现开溜、私生活混乱?董明珠的标签是时候真相大白

被停职审查、套现开溜、私生活混乱?董明珠的标签是时候真相大白

璀璨幻行者
2026-10-13 16:20:30
奢靡荒唐的白马会所:性交易泛滥,让无数富婆挥金如土

奢靡荒唐的白马会所:性交易泛滥,让无数富婆挥金如土

天启大世界
2026-10-13 17:17:54
暂时不用拆,但车企OTA将永久关闭:存量L2小蓝灯何去何从?

暂时不用拆,但车企OTA将永久关闭:存量L2小蓝灯何去何从?

侃故事的阿庆
2026-10-24 05:50:37
比尔盖茨表示:他这辈子犯过最大的错误,就是把原本属于微软的移动生态,拱手让给了安卓

比尔盖茨表示:他这辈子犯过最大的错误,就是把原本属于微软的移动生态,拱手让给了安卓

元气科技馆
2026-10-10 21:56:30
巴萨官方祝贺梅西获奖:你永远是巴萨是一员,是我们骄傲的源泉

巴萨官方祝贺梅西获奖:你永远是巴萨是一员,是我们骄傲的源泉

懂球帝
2026-10-24 02:43:16
场均22分钟!开局连12人名单进不了的张皓嘉,凭什么抢到了出场时间?

场均22分钟!开局连12人名单进不了的张皓嘉,凭什么抢到了出场时间?

弄月公子
2026-10-25 00:27:19
印军突袭巴基斯坦,让6架阵风战机被摧毁,中国军工凭啥惊艳全世界

印军突袭巴基斯坦,让6架阵风战机被摧毁,中国军工凭啥惊艳全世界

睡前讲故事
2025-05-09 11:11:56
2026-10-25 08:31:00
我是一个养虾人
我是一个养虾人
有态度网友ytd
184文章数 92关注度
往期回顾 全部

科技要闻

写程序、做3D,新Kimi还有多少本事?

头条要闻

星链恢复正常服务 泽连斯基发视频:感谢美国

头条要闻

星链恢复正常服务 泽连斯基发视频:感谢美国

体育要闻

从乐透秀到总冠军再到没工作 一共要几年?

娱乐要闻

翁虹19岁女儿三次拒爱,在美国上学却“不随便”

财经要闻

叫"保障"不叫"保险":租车平台的文字游戏

汽车要闻

大众安徽与众09正式上市 双十一权益价16.99万起

态度原创

亲子
教育
数码
健康
公开课

亲子要闻

AB、A型父母生出O型娃,父亲萌生亲子鉴定想法

教育要闻

高考地理:城市功能区的改造

数码要闻

JBL CLIPS琉璃扣耳夹耳机新增“碧玺红色特别版”,1346元

痘痘能根治吗?皮肤科医生说实话

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版