当前位置: 首页 > news >正文

通过try-catch判断数据库唯一键字段是否重复

MyBatis + MySQL 项目里,完全可以通过 try-catch 捕获数据库抛出的唯一约束异常 来判断是否重复,从而避免提前多一次 SELECT 查询。

1、原理

  • MySQL 在插入数据时,如果违反唯一索引约束(Duplicate entry),会抛出 SQL 异常。

  • 通过 MyBatis 调用时,这个异常会被包装成 Java 异常(比如 org.springframework.dao.DuplicateKeyException,如果你用了 Spring;或者原生的 java.sql.SQLIntegrityConstraintViolationException)。

  • 你可以在代码里直接捕获并处理。

示例代码

假设用了spring+MyBaits:

try {myMapper.insert(clue);
} catch (DuplicateKeyException e) {// 这里捕获到 clue_id 唯一索引冲突log.warn("clue_id 已存在: {}", clue.getClueId());// 业务逻辑:例如更新已有数据,或者提示用户
}

如果没用 Spring,只是原生 MyBatis,可以捕获更底层的 SQL 异常:

try {myMapper.insert(clue);
} catch (SQLIntegrityConstraintViolationException e) {if (e.getErrorCode() == 1062) { // 1062 是 MySQL 的 Duplicate entry 错误码log.warn("clue_id 已存在: {}", clue.getClueId());// 业务处理} else {throw e; // 不是唯一约束异常就继续抛出}
}

优点

  • 避免额外的 SELECT 查询,减少一次数据库交互。

  • 并发场景下比 先查再插入 更安全(避免查询和插入之间的 race condition)。

⚠️ 缺点

  • 异常走的是数据库错误路径,开销比普通逻辑分支稍高(但大多数业务场景下可以接受)。

  • 如果异常抛出很频繁,可能会影响性能,最好在业务设计上减少重复的可能。

2、怎么理解“异常走的是数据库错误路径,开销比普通逻辑分支稍高”?

1. 普通逻辑分支 vs 异常机制

在 Java 里,正常的逻辑判断(比如 if 判断)和 异常处理机制(try-catch)的开销是不一样的。

  • 普通逻辑分支:JVM 在执行 if 判断时,基本就是一次条件判断+跳转,开销很小。

  • 异常机制:Java 的 throw 并不是普通返回,它会触发:

    1. 创建异常对象(有可能包含堆栈快照 stack trace)。

    2. 异常从当前方法抛出,逐层回溯,直到找到匹配的 catch。

    3. 如果有 stack trace 打印,还会涉及额外的字符串拼接、I/O。

    所以 throw 本身在 JVM 层面就比 if 要重很多。

2. 数据库层面

当 MySQL 插入违反唯一约束时,它并不是“返回 false”,而是:

  1. 先检测唯一索引冲突。

  2. 如果冲突,则构造错误码(1062)、错误信息(Duplicate entry …)。

  3. 通过驱动(JDBC)抛到 Java。

这意味着你触发了数据库错误路径,数据库和 JDBC 驱动要多做一些额外的处理。

3. 结合起来的理解

所以我说的“异常走的是数据库错误路径,开销比普通逻辑分支稍高”,意思是:

  • 如果你在业务逻辑中 频繁依赖抛异常来做流程控制(比如大量数据都重复,几乎每次插入都报 Duplicate),那开销会比较大:

    • JVM 异常开销高于普通分支。

    • 数据库错误处理开销高于正常 SQL 执行。

  • 但如果你的场景是 大部分数据不会重复,偶尔才会碰到 DuplicateKeyException,那完全可以用 try-catch,因为正常路径走的还是普通 SQL 成功返回,异常的开销只在极少数情况下才体现。

http://www.lryc.cn/news/626587.html

相关文章:

  • linux的内核符号表
  • 【表的操作】
  • 深入理解 Linux 多线程
  • mysql-8.0.37-linux-glibc2.12-x86_64安装
  • 可实现三重空间感知:Ai2 开源具身机器人 AI 模型 MolmoAct
  • 从防抖节流到链表树:编程世界中的抽象优化艺术
  • 23种设计模式——模板方法模式(Template Method Pattern)详解
  • 在一台没联网的机器上,用ollama加载qwen3,14b
  • 遥感机器学习入门实战教程|Sklearn 案例④ :多分类器对比(SVM / RF / kNN / Logistic...)
  • 使用 GraalVM Native Image 将 Spring Boot 应用编译为跨平台原生镜像:完整指南
  • Spring Boot 配置
  • nvidia最新论文:小型语言模型是代理人工智能的未来
  • (5)软件包管理器 yum | Vim 编辑器 | Vim 文本批量化操作 | 配置 Vim
  • 5G-A赋能AR眼镜:毫米级虚实融合的未来已来
  • 开源 AR 眼镜怎么选?OpenGlass ,OSSG,cheApR 分析推荐
  • 给你的Unity编辑器添加实现类似 Odin 的 条件显示字段 (ShowIf/HideIf) 功能
  • 用好 Elasticsearch Ruby 传输层elastic-transport
  • 二维码跳转支付宝、微信小程序二码合一(直接关联、中间页识别跳转)方案
  • python-使用鼠标对图片进行涂抹自定义绘图
  • 自己微调的大模型如何用ollama运行
  • Android 开发问题:android:marginTop=“20px“ 属性不生效
  • 数字化图书管理系统设计实践(java)
  • Redis 复制功能是如何工作的
  • Linux I/O 多路复用实战:Select/Poll 编程指南
  • iOS 应用上架常见问题与解决方案,多工具组合的实战经验
  • Redis--day9--黑马点评--分布式锁(二)
  • C++ 数据结构 和 STL
  • 大数据毕业设计选题推荐-基于大数据的1688商品类目关系分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • wpf之ComboBox
  • 软件测试面试题真题分享