首页 文章 精选 留言 我的

精选列表

搜索[Spring Framework],共10000篇文章
优秀的个人博客,低调大师

《Spring Boot + JPA 实战》第21招 AI写代码也要审SQL

## 01、痛点 凌晨两点,手机报警第三次响起:订单服务 P99 飙到 4.6 秒,数据库 CPU 打满。我打开慢日志,一条看起来普通的订单搜索 SQL 正在对 300 万行主表做全表扫描,还附带 60 多条重复查询。我是老李。这行干了十几年 Java,最近团队把一部分数据访问层交给 AI 生成,效率确实上来了,可这次差点把生产打挂。 问题不是 AI 写得不好,而是我们用审 Java 代码的旧办法,审了一套运行时才会露馅的 JPA 代码。一个复杂订单搜索接口,入参包括订单号、客户昵称、状态、商品 SKU、下单时间范围、金额区间和排序字段。AI 生成的 Entity、Repository、动态查询代码看起来规范,方法命名清晰,映射关系也像那么回事。代码评审时,我们只盯着 Java 类看,没有把生成的 SQL 拉出来认真看一遍,更别提执行计划。 结果就是:测试环境数据量小,一切正常;生产数据量上来后,索引缺失、N+1 查询、事务边界过大这些问题全冒出来。AI 编码越快,这类风险进入生产的速度也越快。过去一个资深工程师一天写三个 Repository,现在三分钟生成十个。代码审查如果还停留在肉眼扫 Java 的阶段,根本拦不住运行时性能事故。 为什么现在要讲这件事?因为数据访问层正在成为 AI 编码的重灾区:生成得快、长得像、跑得慢。我们需要的不是禁用 AI,而是一套专门针对数据访问的评审门禁,把检查范围从代码延伸到 SQL 和执行计划。 ## 02、是什么 我把它总结为六道数据访问门禁:Entity Review、Repository Review、SQL Count、Execution Plan、Index Review、Transaction Boundary。这六道门禁从静态代码一路查到运行时行为,分别回答不同的问题。 第一道,Entity Review。重点看实体映射、关联关系、抓取策略、继承、枚举、ID 生成方式,以及是否存在无意义的大对象映射。常见问题包括把双向关联配成全 EAGER,导致每次查询都拖家带口;或者用数据库默认的字符串映射,把大字段也加载出来。 第二道,Repository Review。重点看仓库方法语义、查询条件拼接、分页与排序、返回值类型、批量操作边界。很多 AI 生成的仓库方法会返回完整实体,而不是投影 DTO;还有一些动态查询在没有条件时直接查全表。 第三道,SQL Count。统计一次业务操作实际触发多少条 SQL。比如一次分页查询,可能先查一次 count,再查一次主列表,然后逐条查明细、客户、商品,形成 N+1。只读代码看不出问题,只有统计 SQL 条数才能暴露。 第四道,Execution Plan。对关键 SQL 看执行计划,确认走没走索引、是否全表扫描、有没有 Using temporary、Using filesort、回表次数是否过高。执行计划会直接展示数据库成本决策。 第五道,Index Review。检查过滤条件、排序字段、关联外键是否被索引覆盖,联合索引是否符合最左前缀原则,是否存在大量冗余索引或缺失的唯一约束。索引问题在 Java 代码里完全无感。 第六道,Transaction Boundary。检查事务边界、传播行为、隔离级别、锁范围与持有时间。一个列表查询如果开启默认事务,可能会无意义地持有快照;一个批量更新如果事务粒度过大,会扩大锁竞争。 这六道门禁有一个共同特点:它们关心的不是代码长什么样,而是代码跑起来什么样。 ## 03、为什么 为什么只做 Java Code Review 已经不够?因为 JPA 这类对象关系映射框架隐藏了 SQL,而 Java 代码只描述映射意图,不描述执行方式。你用眼睛看 findByOrderDateBetweenAndStatus,以为只是一个简单查询;实际上它可能生成一条 select * from orders where order_date between ? and ? and status = ?,但没有索引时就是全表扫描。 更麻烦的是,很多 JPA 性能问题只存在于运行时。N+1 查询、懒加载触发在事务外、分页与多对多关联同时使用、In 条件超过数据库限制、锁扩散、事务过长,这些问题在静态 Java 代码里几乎不可见。代码评审者如果没有 SQL 和执行计划,就像只在图纸上检查建筑,没有去工地看地基和管线。 AI 提升的是代码生成速度,而不是数据访问设计正确性。一个复杂的订单搜索接口,AI 可以飞快生成 Entity、Repository 和查询封装,但它不知道订单表有 300 万行,不知道状态字段选择性低,不知道客户外键上没有索引,也不知道业务高峰期会有多少并发。这些知识需要从数据库统计信息、慢日志和运行监控中获得,而不是从代码生成过程中天然获得。 所以数据访问 Review 必须从代码审查升级为代码 + SQL + 执行计划审查。代码回答想做什么,SQL 回答实际做了什么,执行计划回答数据库会怎么执行。三者合在一起,才能形成完整的数据访问评审证据链。 ## 04、架构 我在团队里落地时,把六道门禁嵌进合并请求评审流程中,形成一条数据访问评审链。大致结构如下: 代码生成层:生成 Entity、Repository、查询封装和服务调用。生成速度很快,但这里不直接合并。 静态检查层:对 Java 代码做 Entity Review 和 Repository Review,检查映射、关联、抓取策略、查询方法、分页排序等。 运行捕获层:在测试或预发环境运行接口,开启 SQL 统计,抓取 SQL Count,并记录每条 SQL 的耗时、参数和执行计划。 数据库分析层:对关键 SQL 做 Execution Plan Review,同时结合表结构、索引和统计信息做 Index Review。 事务分析层:检查事务边界、隔离级别和锁等待,完成 Transaction Boundary Review。 评审决策层:以上证据汇总到 PR 页面或评审报告里。普通数据访问改动需要至少通过静态与运行两层检查;复杂查询 PR 必须附关键 SQL 或执行计划,否则不能合并。 这套架构不复杂,关键是把 SQL 和执行计划变成和 Java 代码同等地位的一等公民。以前我们看 PR 只看 diff,现在还要看 diff 对应的 SQL 和执行计划附件。工具可以自动生成一份数据访问评审摘要,放在 PR 页面上,让评审人一眼看到本次改动新增 4 条 SQL,其中一条全表扫描,建议补索引。 ## 05、实战 拿一个真实场景说明:让 AI 生成一个复杂订单搜索接口。需求是分页查询订单列表,支持订单号、客户昵称、状态、商品 SKU、下单时间范围、金额区间,支持按创建时间和金额排序。AI 很快生成了 OrderEntity、OrderItemEntity、CustomerEntity、ProductEntity,以及对应的 Repository 和动态查询封装。 先做 Entity Review。我发现 OrderEntity 里把 CustomerEntity 和 ProductEntity 都配成了 EAGER,而 OrderItemEntity 虽然配置了 LAZY,但 Service 里在循环中读取了订单明细,最终触发 N+1。另外实体直接暴露了数据库表结构,连内部状态字段也映射出来,导致查询返回列过宽。 再做 Repository Review。动态查询封装在没有传入状态和时间范围时,会生成一条无条件分页查询;排序字段直接拼接到 Sort.by 中,没有校验白名单,有安全风险;分页 count 查询默认使用主查询的关联条件,导致 count 和主查询都重复 join。 然后做 SQL Count。开启 SQL 统计后,一次 20 条订单的分页请求,实际触发了 1 条 count、1 条主列表查询、20 条订单明细查询、20 条客户查询,总共 62 条 SQL。这就是典型的 N+1。 接着看 Execution Plan。主列表查询的 explain 结果显示 type=ALL,key=NULL,Extra 里出现了 Using temporary 和 Using filesort;count 查询扫描了 300 万行。数据库明确告诉我们:这条 SQL 在裸跑。 再检查 Index Review。订单表的 order_date、status 上没有联合索引,客户外键上也没有索引,导致关联查询全表扫描。状态字段单独建索引选择性很低,但和订单日期组合后可以选择性很高。于是我们增加了 idx_orders_date_status 和 idx_orders_customer_id,并把排序字段纳入覆盖索引。 最后看 Transaction Boundary。列表查询开启了默认可重复读事务,在事务里执行了 62 条 SQL 并组装数据。这个事务从第一次查询一直持有到远程日志调用结束,快照保留时间过长,拖累了数据库版本链。批量更新操作还使用了单事务逐条执行,锁范围被无谓扩大。 优化改了三处:把 EAGER 改成 LAZY,列表查询改成 DTO 投影,显式写 countQuery 并删除多余关联;补上联合索引和覆盖索引;列表查询改成只读事务,批量更新拆成小事务。优化后,一次 20 条订单的分页请求,SQL 从 62 条降到 2 条,主查询执行计划从 ALL 变成 ref,耗时从 1.8 秒降到 80 毫秒左右。 这个例子说明,如果只做 Java Code Review,我们大概率会直接通过这段 AI 生成的代码。只有把 SQL Count、Execution Plan、Index Review、Transaction Boundary 全部跑一遍,才能拦住这场生产事故。 ## 06、洞见 这次实战让我更坚定一个判断:AI 提升的是代码生成速度,而很多 JPA 问题存在于运行时。代码是设计意图的静态描述,SQL 是实际执行路径的体现,执行计划是数据库成本决策。只审 Java 代码,等于只检查图纸,没有去看施工和地基。 未来代码生成越普及,人工评审越要往运行时证据倾斜。执行计划、SQL 统计、锁等待、慢日志,这些本来是数据库管理员和运维关心的东西,会越来越多出现在开发评审页面上。一个复杂 PR 如果没有附关键 SQL 或执行计划,就不应该被视为一个完整的数据访问改动。 这不是说要让 Java 开发都变成数据库管理员,而是数据访问评审的最小单元必须从 Java 文件扩展到代码 + SQL + 执行计划。只有把运行时事实拉到评审桌上,才能避免代码看起来都对,生产跑起来全错的尴尬。 ## 07、行动 第一,把六道门禁写进团队开发规范。尤其是复杂查询接口,必须通过 Entity、Repository、SQL Count、Execution Plan、Index、Transaction 六项检查后才能合并。 第二,复杂 PR 必须附关键 SQL 或执行计划。比如订单搜索接口的 PR 里,要贴出主查询的 explain 结果、SQL 条数统计和关键索引说明。没有这些材料,评审可以直接打回。 第三,在测试或预发环境开启 SQL 日志、慢查询阈值和执行计划抓取。让每次数据访问改动都能自动产出运行证据,而不是靠人肉去数据库里翻。 第四,结合表统计信息和数据量做索引收益判断。不要只看字段有没有索引,要看索引选择性、联合索引前缀和覆盖情况。数据量越大,索引决策越不能拍脑袋。 第五,对订单搜索这类核心接口做容量演练。用接近生产的数据量验证执行计划是否稳定,是否存在数据量增长后从 ref 变成 ALL 的风险。 第六,定期回看慢查询日志,把运行时慢 SQL 映射回代码调用链。形成闭环:生产发现慢查询,反向补充六道门禁的检查规则,避免同类问题再次进入代码库。 ## 08、小结 AI 编码确实快,但数据访问层的正确性和性能不会因为生成速度快就自动变好。我们真正需要的,是一套把检查范围从 Java 代码延伸到 SQL 和执行计划的门禁。 复杂订单搜索接口的例子已经说明:60 多条 SQL、全表扫描、缺失索引和过大事务,都可以藏在看似规范的 JPA 代码后面。只看 Java 代码,很容易放行;只有把 SQL Count、Execution Plan、Index Review、Transaction Boundary 这些运行时证据拉出来,才能把风险拦在生产之前。 一句话收尾:代码写得快,不如数据库跑得稳;PR 里多一张执行计划,生产少一次半夜救火。 ## 09、链接与概念说明 JPA / ORM:对象关系映射框架,用 Java 对象映射数据库表,方法调用时可自动生成 SQL。优点是开发快,缺点是 SQL 对开发者半透明,容易出现运行时性能问题。 Entity:领域实体,映射数据库表结构。在 AI 生成的数据访问层中,实体常包含映射注解、关联关系和抓取策略。 Repository:仓库接口,封装增删改查和查询方法。AI 生成的仓库方法可能语义不清、返回实体过重、分页排序不严谨。 SQL Count:统计一次业务操作实际触发的 SQL 条数。用于发现 N+1 查询、重复查询和多余更新。 Execution Plan:数据库执行计划,展示 SQL 的访问路径、扫描方式、索引使用、排序和临时表。判断 SQL 是否高效的核心依据。 Index Review:检查索引是否覆盖过滤、排序、关联字段,是否符合最左前缀原则,是否有冗余或缺失。 Transaction Boundary:事务边界与隔离级别,影响锁范围、持有时间和并发能力。只读查询应避免长事务,批量更新应控制事务粒度。 文中提到的慢查询日志、执行计划、统计信息,可以在数据库控制台和监控平台中查看。建议团队将这类运行时信息纳入常规评审材料,而不是只在事故发生后复盘。

优秀的个人博客,低调大师

maku-boot v4.11.0 已经发布,Spring Boot 快速开发系统

maku-boot v4.11.0 已经发布,SpringBoot 快速开发系统。 更新日志: 新增用户签名功能,满足审批等需求 重构登录页面,更加符合后台系统风格 优化定时任务功能,支持查看单任务日志 优化页面布局,把工作台页面改成首页 修复ma-data-table组件,效验报警告问题 升级 SpringBoot 到 3.5.8 升级 ElementPlus 到 2.11.9 升级 Vite 到 6.4.1 详情查看:https://gitee.com/makunet/maku-boot/releases/v4.11.0

优秀的个人博客,低调大师

实战指南:利用React与Spring Boot开发协同编辑的表格文档

前言 随着云计算和团队协作的兴起,协同编辑成为了许多企业和组织中必不可少的需求。通过协同编辑,多个用户可以同时对同一个文档进行编辑和更新,从而提高工作效率和协作能力。本文小编就将为大家介绍如何使用React+SpringBoot简单的开发一个协同编辑的表格文档。 环境准备 用到的开发工具: 前端开发工具:VSCode 后端开发工具:IDEA 用到的组件: 葡萄城公司前端表格控件SpreadJSV14.0.0和SpreadJS在线表格编辑器react组件版 葡萄城公司服务端表格组件GrapeCity Documents for Excel 实现步骤 1.搭建前端项目 首先,前端新建react项目,并按照下面图所示引入SpreadJS以及设计器组件版的相关引用。 然后,集成在线表格编辑器react组件版。 这样前端的准备工作就完成了。 2.搭建后端项目 后端的准备工作,首先安装gradle作为包管理器。当然,这里也可以用其他工具来代替,例如maven,或者源生引入jar包的方式将需要用到的jar包引入进来。然后创建springboot工程配合搭建gradle引用GCExcel以及后面协同需要用到的websocket。 这样后端的准备工作也完成了。 3.核心代码的构建 3.1前端代码 **首先是前端,**既然要做协同,那么首先就要搭建websocket。 在react中使用websocket不需要引入其他库,只需要创建一个公共组件,封装一下websocket,接下来我们需要监听前端发出的操作。这里因为在线表格编辑器本身将所有用户可能做的操作全部做了封装,所以省下了很多的功夫。 然后对命令再做一些简单封装: 紧接着将封装过的命令发到服务端,之后通过websocket发同步指令: 当协同端通过websocket接收到请求的时候,通过onmessage方法做同步命令,这里在协同端执行command之前需要先撤销之前的监听,避免再发送websocket导致死循环。在执行之后,再次添加监听。 3.2后端代码 这样前端的核心内容就介绍完了,目前前端这样做已经能做基本的协同操作了。 接下来是后端的相关核心代码: 首先,后端搭建对应的websocket: 之后设置websocket的过期时间,当session关闭后5分钟停止给该端口发送websocket请求: 3.3前后端交互 前端发送请求至后端: 后端接收请求后,根据请求在后端重写对应的实现,demo中走了封装使得结构上更加合理,方便重写: 然后在后端GCExcel中加载同一个文档并执行上述操作: 总结 ​ 使用SpreadJS+GcExcel开发一个协同编辑的表格文档,可以实现多人同时编辑、即时保存和实时更新的功能。通过这种方式,可以提高团队协作效率,确保数据的准确性和一致性。同时,SpreadJS和GcExcel提供了丰富的API和功能,可以满足各种复杂的表格需求,为用户提供良好的使用体验。总的来说,这种开发方式能够为企业带来更高的工作效率和更好的用户体验。 扩展链接: 如何使用Java + React计算个人所得税? Vite+React构建前端在线表格 项目实战:在线报价采购系统(React +SpreadJS+Echarts)

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册