ORM 最佳实践(Hibernate N+1、MyBatis 优化、JPA vs JDBC)

共 19 题
#

1. Hibernate N+1 查询问题的成因,懒加载关联对象导致 1+N 次 SQL?

A N+1 指查询父记录时只发一条 SQL
B N+1 问题只影响写入不影响查询
C 懒加载关联在遍历访问时逐条查询,导致 1+N 次 SQL,是 N+1 问题的成因 ✓ 正确答案
D 禁用懒加载能彻底消除所有查询
#

2. N+1 问题的解决方案,JOIN FETCH、@EntityGraph、@BatchSize、子查询 FETCH?

A @BatchSize 无法减少 SQL 次数
B JOIN FETCH 一次取齐关联,但可能产生笛卡尔膨胀;@BatchSize 用 IN 批量加载也有帮助 ✓ 正确答案
C 子查询 FETCH 只能一次加载一条关联
D JOIN FETCH 对分页没有任何影响
#

3. MyBatis 的 ExecutorType.BATCH 与 JDBC BATCH 的性能差异与正确用法?

A BATCH 模式下无需控制批大小
B BATCH 执行器不会缓存任何 PreparedStatement
C 它使用 JDBC 批量执行合并多条 SQL 减少往返,需配合 rewriteBatchedStatements 等参数提升效果 ✓ 正确答案
D BATCH 与普通执行方式性能完全相同
#

4. JPA vs JDBC vs MyBatis,不同场景下的选型依据与性能权衡?

A JPA 的性能一定比 JDBC 高
B JPA 抽象最高、开发快但 SQL 隐藏;MyBatis 半自动可精细控制 SQL;JDBC 最底层、性能最高但开发量大 ✓ 正确答案
C MyBatis 完全不需要写 SQL
D JDBC 开发效率最高
#

5. ORM 批量写入的批大小与 flush 策略(JDBC batch 与 Hibernate 的 flush 模式)

A 批大小应尽量大,无限累积
B 批处理不需要考虑事务长度
C Hibernate `flush` 模式与批处理无关
D 需控制批大小与 flush 时机,Hibernate 用 MANUAL/AUTO 配合分批 flush 与 clear 控制内存与事务长度 ✓ 正确答案
#

6. 只读事务(readOnly=true)为什么能提升性能?跳过脏检查与 flush、连接只读路由与数据库端只读优化的机制是什么?

A readOnly 事务会额外执行脏检查与 flush
B readOnly=true 会强制该事务写操作一定成功
C 它跳过脏检查与 flush、可路由到只读副本,并利用数据库只读优化提升性能 ✓ 正确答案
D readOnly 事务与普通事务性能完全相同
#

7. ORM 分页生成的 SQL 与方言差异(LIMIT/OFFSET、ROW_NUMBER)如何影响性能?深分页为什么慢、keyset 分页如何改写?

A ROW_NUMBER 分页与 OFFSET 分页性能完全一致
B LIMIT/OFFSET 在所有数据库下性能都相同
C keyset 分页适合任意随机跳页
D 深分页 OFFSET 越大越慢,因为要扫描并丢弃大量行;keyset 用排序键条件定位走索引来优化 ✓ 正确答案
#

8. Open Session in View(OSIV)模式的风险,长 Session 导致连接池耗尽与 LazyInitializationException?

A OSIV 与 LazyInitializationException 无关
B OSIV 能缩小连接占用时间
C OSIV 让 Session 在请求期间保持打开以支持懒加载,但会长时间占用连接导致连接池耗尽 ✓ 正确答案
D OSIV 适合高并发场景
#

9. Hibernate 的 StatelessSession 与无状态批量操作优化?

A StatelessSession 支持懒加载
B StatelessSession 会维护完整实体状态
C StatelessSession 性能比普通 Session 更差
D StatelessSession 跳过持久化上下文与脏检查,适合批量操作,但失去缓存与级联等特性 ✓ 正确答案
#

10. MyBatis 的 foreach 批量插入与 rewriteBatchedStatements 的协同优化?

A foreach 生成多值 INSERT,rewriteBatchedStatements 让驱动合并批量 SQL,两者协同减少往返提升性能 ✓ 正确答案
B rewriteBatchedStatements 与批量插入无关
C foreach 每次都会拆成多条单行 INSERT
D 批大小不受 max_allowed_packet 影响
#

11. Hibernate 的 @Version 乐观锁实现与 OptimisticLockException 处理?

A 乐观锁通过版本号作为更新条件,冲突时抛 OptimisticLockException,需重新加载数据并重试或提示 ✓ 正确答案
B 乐观锁会持有数据库锁,并发低
C 乐观锁无需版本字段
D OptimisticLockException 只能忽略
#

12. MyBatis 的 ${} 与 #{} 的安全差异,SQL 注入风险?

A ${} 与 #{} 安全性相同
B #{} 走参数化绑定防注入,${} 做字符串拼接存在注入风险,应仅用于可信白名单场景 ✓ 正确答案
C #{} 会把值直接拼进 SQL 文本
D ${} 适合直接拼接用户输入
#

13. MyBatis 的批处理,ExecutorType.BATCH 与 foreach insert?

A ExecutorType.BATCH 复用 PreparedStatement 累积批处理,foreach 生成多值 INSERT,两者都是批量手段但机制不同 ✓ 正确答案
B BATCH 与 foreach 完全相同
C foreach 无法实现批量插入
D BATCH 不需要控制批大小
#

14. Hibernate/JPA 的 DTO 投影(Constructor Expression/Interface Projection)与实体查询的性能差异

A DTO 投影支持完整的懒加载级联
B DTO 投影会加载所有列并纳入缓存
C 实体查询比 DTO 投影更省内存
D DTO 投影只取所需列且不进入持久化上下文,性能更轻量,适合只读场景 ✓ 正确答案
#

15. 批量写为什么需要分批提交?max_allowed_packet 与批大小、事务长度如何权衡,失败时整批回滚的粒度如何设计?

A 失败时只能整批全部回滚,无法部分成功
B 一次提交越多越好
C max_allowed_packet 与批大小无关
D 批大小需权衡 max_allowed_packet、事务长度与内存,采用"每批一个事务"以控制回滚粒度 ✓ 正确答案
#

16. Hibernate 的 @NaturalId 缓存与二级缓存的关系?自然键查找如何减少 SQL 往返?

A 自然键缓存挂在二级缓存之上,按自然键查找可先命中缓存减少数据库往返 ✓ 正确答案
B 自然键缓存与二级缓存无关
C 自然键查找一定会查数据库
D 自然键缓存无法缓存实体
#

17. JPA(Java Persistence API)的 EntityGraph 与 Criteria API 动态查询?

A Criteria API 使用字符串拼接 SQL,有注入风险
B EntityGraph 无法控制抓取路径
C EntityGraph 控制关联抓取避免 N+1,Criteria 提供类型安全动态查询,两者可结合使用 ✓ 正确答案
D EntityGraph 与 Criteria 不能一起使用
#

18. ORM 生成 SQL 的审查(show-sql、格式化、慢 SQL 定位)

A show-sql 会拖慢所有查询,无法开启
B show-sql 打印生成的 SQL,配合格式化与 EXPLAIN 执行计划可定位慢 SQL 与 N+1 等问题 ✓ 正确答案
C ORM 生成的 SQL 无需审查
D 慢 SQL 只能靠数据库慢日志,与 ORM 无关
#

19. ORM 会话何时获取数据库连接(延迟获取)?与连接池超时、事务边界如何配合避免长事务占连接?

A 打开 Session 就应立即获取连接
B 连接常延迟到执行 SQL 时才获取,事务应短小快提交,Session 与事务边界对齐以避免长事务占连接 ✓ 正确答案
C 事务内可以做任意耗时操作
D 连接池超时与长事务无关