Mybatis UUID應用詳解

一、UUID概述

UUID是一種由網絡通用唯一標識符(Universally Unique Identifier)的縮寫,是由一組32位數字的十六進制數所構成。其核心思想是通過網絡傳輸來確保唯一性,即使全球範圍內的標識符不會重複。一般情況下,有32位字符,被表示成8-4-4-12的形式,其中4組數分別表示時間戳、計算機代碼、隨機位、全局唯一標識符。UUID的生成是基於時間、節點標識、序列號三維組合的,因此理論上不存在重複的風險。在Java生態系統中,最常用的UUID實現無疑就是java.util.UUID類了。

二、Mybatis中的UUID應用

在Mybatis框架中,UUID作為主鍵生成策略廣泛被運用。Mybatis提供了兩種主鍵生成方式:數據庫自增ID和UUID,而前者需要保證在數據庫服務器上需要單獨聲明主鍵域為自增長型,否則無法正常生成。因此,UUID的生成策略被廣泛應用於分布式環境下的主鍵生成。

三、Mybatis UUID生成方式

Mybatis中使用UUID作為主鍵生成策略,需要在Mapper.xml的insert節點中使用java.util.UUID的randomUUID()靜態方法來為主鍵賦值。下面是一個示例:

<insert id="insertUser" parameterType="User">
   <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"/>
   INSERT INTO user (
       id,
       name,
       age,
       address
   ) VALUES (
       #{id},
       #{name},
       #{age},
       #{address}
   )
</insert>

在這個偽代碼中,selectKey元素可以設置兩個屬性:keyProperty和resultType。其中keyProperty屬性是JavaBean在數據庫中主鍵的名稱,resultType屬性是把UUID生成的字符串設置給JavaBean主鍵的屬性類型。

四、Mybatis UUID性能優化

雖然UUID理論上不會重複,但是使用UUID作為主鍵生成策略時,在大量數據插入的情況下,也會存在性能瓶頸。此時,我們需要對Mybatis的UUID生成策略進行優化,提高性能。常用優化方式如下:

  • 使用JDBC批量操作:將多個INSERT操作合併成一個批量INSERT操作,減少通信開銷,提高性能。
  • 使用Mybatis插件:使用Mybatis插件可以對UUID生成策略進行動態代理,攔截Executor的query和update方法,實現自定義的UUID生成方式。
  • 緩存UUID:對UUID進行緩存,減少生成UUID的次數,提高性能。

五、Mybatis插件示例

以下示例僅供參考,具體可根據實際情況進行修改:

public class UUIDInterceptor implements Interceptor {
    private static final String SELECT_PREFIX = "__select_uuid";
    private static final String UPDATE_PREFIX = "__update_uuid";
 
    private final Cache uuidCache = new SynchronizedCache(new LruCache(1024));
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        String statement = ((MappedStatement) args[0]).getId();
        Object parameter = args[1];
        BoundSql boundSql = ((MappedStatement) args[0]).getBoundSql(parameter);
        String sql = boundSql.getSql().toLowerCase(Locale.CHINA);
 
        if (StringUtils.isNotBlank(sql) && (sql.trim().startsWith("insert") || sql.trim().startsWith("update"))) {
            if (StringUtils.isNotBlank(statement) && statement.trim().toLowerCase(Locale.CHINA).startsWith(UPDATE_PREFIX)) {
                // update語句中,不能替換主鍵
                return invocation.proceed();
            }
            Field idField = ReflectionUtils.findField(parameter.getClass(), "id");
            if (idField == null) {
                return invocation.proceed();
            }
            ReflectionUtils.makeAccessible(idField);
            Object idValue = idField.get(parameter);
 
            // 如果id已經被賦值了,則不需要再生成
            if (StringUtils.isNotBlank(String.valueOf(idValue))) {
                return invocation.proceed();
            }
            UUID uuid = UUID.randomUUID();
            if (StringUtils.isNotBlank(statement) && statement.trim().toLowerCase(Locale.CHINA).startsWith(SELECT_PREFIX)) {
                uuidCache.put(uuid, null);
            }
            idField.set(parameter, uuid.toString().replaceAll("-", ""));
        }
        return invocation.proceed();
    }
 
    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }
 
    @Override
    public void setProperties(Properties properties) {
    }
}

上述示例是一個簡單的UUID生成器攔截器實現,用於攔截Executor的query和update方法並提供自定義的UUID生成策略。由於該示例僅供參考,實際使用時需要結合實際業務需求進行改進。

原創文章,作者:DTIMK,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/334141.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
DTIMK的頭像DTIMK
上一篇 2025-02-05 13:05
下一篇 2025-02-05 13:05

相關推薦

  • 理解Mybatis中的SQL Limit用法

    Mybatis是一種非常流行的ORM框架,提供了SQL映射配置文件,可以使用類似於傳統SQL語言的方式編寫SQL語句。其中,SQL的Limit語法是一個非常重要的知識點,能夠實現分…

    編程 2025-04-29
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分布式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和算法 C語言貪吃蛇主要運用了以下數據結構和算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25

發表回復

登錄後才能評論