如何通過try-catch判斷數(shù)據(jù)庫唯一鍵字段是否重復
在 MyBatis + MySQL 項目里,完全可以通過 try-catch 捕獲數(shù)據(jù)庫拋出的唯一約束異常 來判斷是否重復,從而避免提前多一次 SELECT 查詢。
1、原理
- MySQL 在插入數(shù)據(jù)時,如果違反唯一索引約束(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());
// 業(yè)務邏輯:例如更新已有數(shù)據(jù),或者提示用戶
}如果沒用 Spring,只是原生 MyBatis,可以捕獲更底層的 SQL 異常:
try {
myMapper.insert(clue);
} catch (SQLIntegrityConstraintViolationException e) {
if (e.getErrorCode() == 1062) { // 1062 是 MySQL 的 Duplicate entry 錯誤碼
log.warn("clue_id 已存在: {}", clue.getClueId());
// 業(yè)務處理
} else {
throw e; // 不是唯一約束異常就繼續(xù)拋出
}
}? 優(yōu)點
- 避免額外的 SELECT 查詢,減少一次數(shù)據(jù)庫交互。
- 并發(fā)場景下比 先查再插入 更安全(避免查詢和插入之間的 race condition)。
?? 缺點
- 異常走的是數(shù)據(jù)庫錯誤路徑,開銷比普通邏輯分支稍高(但大多數(shù)業(yè)務場景下可以接受)。
- 如果異常拋出很頻繁,可能會影響性能,最好在業(yè)務設計上減少重復的可能。
2、怎么理解“異常走的是數(shù)據(jù)庫錯誤路徑,開銷比普通邏輯分支稍高”?
1. 普通邏輯分支 vs 異常機制
在 Java 里,正常的邏輯判斷(比如 if 判斷)和 異常處理機制(try-catch)的開銷是不一樣的。
- 普通邏輯分支:JVM 在執(zhí)行 if 判斷時,基本就是一次條件判斷+跳轉,開銷很小。
- 異常機制:Java 的 throw 并不是普通返回,它會觸發(fā):
- 所以 throw 本身在 JVM 層面就比 if 要重很多。
- 創(chuàng)建異常對象(有可能包含堆??煺?stack trace)。
- 異常從當前方法拋出,逐層回溯,直到找到匹配的 catch。
- 如果有 stack trace 打印,還會涉及額外的字符串拼接、I/O。
2. 數(shù)據(jù)庫層面
當 MySQL 插入違反唯一約束時,它并不是“返回 false”,而是:
- 先檢測唯一索引沖突。
- 如果沖突,則構造錯誤碼(1062)、錯誤信息(Duplicate entry …)。
- 通過驅動(JDBC)拋到 Java。
這意味著你觸發(fā)了數(shù)據(jù)庫錯誤路徑,數(shù)據(jù)庫和 JDBC 驅動要多做一些額外的處理。
3. 結合起來的理解
所以我說的“異常走的是數(shù)據(jù)庫錯誤路徑,開銷比普通邏輯分支稍高”,意思是:
- 如果你在業(yè)務邏輯中 頻繁依賴拋異常來做流程控制(比如大量數(shù)據(jù)都重復,幾乎每次插入都報 Duplicate),那開銷會比較大:
- JVM 異常開銷高于普通分支。
- 數(shù)據(jù)庫錯誤處理開銷高于正常 SQL 執(zhí)行。
- 但如果你的場景是 大部分數(shù)據(jù)不會重復,偶爾才會碰到 DuplicateKeyException,那完全可以用 try-catch,因為正常路徑走的還是普通 SQL 成功返回,異常的開銷只在極少數(shù)情況下才體現(xiàn)。
到此這篇關于如何通過try-catch判斷數(shù)據(jù)庫唯一鍵字段是否重復的文章就介紹到這了,更多相關try-catch判斷數(shù)據(jù)庫字段是否重復內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中的do while循環(huán)控制語句基本使用
這篇文章主要介紹了Java中的do while循環(huán)控制語句基本使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳
本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();2022-02-02
如何自定義hibernate validation注解示例代碼
Hibernate Validator 是 Bean Validation 的參考實現(xiàn) . Hibernate Validator 提供了 JSR 303 規(guī)范中所有內置 constraint 的實現(xiàn),下面這篇文章主要給大家介紹了關于如何自定義hibernate validation注解的相關資料,需要的朋友可以參考下2018-04-04
SpringBoot如何使用Scala進行開發(fā)的實現(xiàn)
這篇文章主要介紹了SpringBoot如何使用Scala進行開發(fā)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12
SpringMVC的處理器攔截器HandlerInterceptor詳解
這篇文章主要介紹了SpringMVC的處理器攔截器HandlerInterceptor詳解,SpringWebMVC的處理器攔截器,類似于Servlet開發(fā)中的過濾器Filter,用于處理器進行預處理和后處理,需要的朋友可以參考下2024-01-01

