【Mytais系列】Type模塊:類型轉換

MyBatis 的 類型系統(Type System) 是框架處理 Java 類型與數據庫類型之間映射的核心模塊,它通過 類型處理器(TypeHandler)類型別名(TypeAlias)類型轉換器 等機制,實現了數據庫字段與 Java 對象屬性的無縫轉換。以下是其核心功能、使用場景及實現原理的詳解:


一、類型系統的核心組件

組件

作用

TypeHandler

處理 Java 類型與 JDBC 類型之間的轉換(如 String ? VARCHAR)。

TypeAlias

為 Java 類型定義別名,簡化 XML 配置中的類型名稱。

TypeHandlerRegistry

全局注冊所有 TypeHandler,管理類型與處理器的映射關系。

ObjectFactory

創建結果集映射的 Java 對象實例(如 POJO、集合等)。


二、類型處理器(TypeHandler)

1. 功能與職責
  • 雙向轉換
    • 寫入數據庫:將 Java 對象屬性轉換為 JDBC 參數(PreparedStatement.setXxx)。
    • 讀取數據庫:將 JDBC 結果集(ResultSet.getXxx)轉換為 Java 對象屬性。
  • 支持復雜類型
    • 枚舉、集合、自定義對象、JSON 字符串等。
2. 內置 TypeHandler

MyBatis 默認注冊了常見類型的處理器,例如:

Java 類型

JDBC 類型

對應 TypeHandler

String

VARCHAR

StringTypeHandler

Integer

INTEGER

IntegerTypeHandler

Date

TIMESTAMP

DateTypeHandler

boolean

BOOLEAN

BooleanTypeHandler

枚舉類

VARCHAR

EnumTypeHandler(按名稱存儲)

枚舉類(按序數存儲)

INTEGER

EnumOrdinalTypeHandler

3. 自定義 TypeHandler

當默認處理器無法滿足需求時(如處理 JSON 字段),可自定義 TypeHandler

示例:將 Java 對象序列化為 JSON 字符串存入數據庫

// 1. 實現 TypeHandler 接口
@MappedTypes(User.class)    // 指定處理的 Java 類型
@MappedJdbcTypes(JdbcType.VARCHAR)  // 指定對應的 JDBC 類型
public class JsonTypeHandler implements TypeHandler<User> {private final ObjectMapper objectMapper = new ObjectMapper();// 寫入數據庫時,將 User 對象轉為 JSON 字符串@Overridepublic void setParameter(PreparedStatement ps, int i, User parameter, JdbcType jdbcType) throws SQLException {try {String json = objectMapper.writeValueAsString(parameter);ps.setString(i, json);} catch (JsonProcessingException e) {throw new SQLException("JSON 序列化失敗", e);}}// 從數據庫讀取時,將 JSON 字符串轉為 User 對象@Overridepublic User getResult(ResultSet rs, String columnName) throws SQLException {String json = rs.getString(columnName);return parseJson(json);}// 其他重載方法(如 getResult(ResultSet rs, int columnIndex))// ...private User parseJson(String json) {try {return objectMapper.readValue(json, User.class);} catch (JsonProcessingException e) {throw new RuntimeException("JSON 解析失敗", e);}}
}

注冊自定義 TypeHandler

<!-- mybatis-config.xml -->
<typeHandlers><typeHandler handler="com.example.JsonTypeHandler"/>
</typeHandlers>

在 Mapper 中使用

<resultMap id="userResultMap" type="User"><result column="json_data" property="data" typeHandler="com.example.JsonTypeHandler"/>
</resultMap>

三、類型別名(TypeAlias)

1. 功能
  • 簡化配置:為長類名定義短別名,避免 XML 中重復書寫全限定類名。
  • 提升可讀性:例如將 java.util.List 別名為 list
2. 使用方式

方式一:XML 配置

<!-- mybatis-config.xml -->
<typeAliases><typeAlias type="com.example.User" alias="User"/><package name="com.example.dto"/> <!-- 自動掃描包下所有類,別名為首字母小寫的類名 -->
</typeAliases>

方式二:注解配置

@Alias("User")  // 在類上添加注解
public class User { ... }

在 Mapper 中使用別名

<select id="getUser" resultType="User">  <!-- 直接使用別名 -->SELECT * FROM users WHERE id = #{id}
</select>

四、類型處理器注冊表(TypeHandlerRegistry)

1. 職責
  • 全局管理 TypeHandler:維護 Java類型 ? JDBC類型 ? TypeHandler 的映射關系。
  • 自動發現機制:通過 <typeHandlers> 配置或掃描包路徑注冊處理器。
2. 優先級規則

當多個 TypeHandler 可處理同一類型時,按以下順序選擇:

  1. 顯式指定 typeHandler 屬性的處理器。
  2. 注解 @MappedTypes@MappedJdbcTypes 精確匹配的處理器。
  3. 默認注冊的處理器(如 StringTypeHandler)。

五、常見應用場景

1. 處理枚舉類型
  • 按名稱存儲(默認):使用 EnumTypeHandler,將枚舉的 name() 存入數據庫。
  • 按序數存儲:使用 EnumOrdinalTypeHandler,將枚舉的 ordinal() 存入數據庫。
  • 自定義存儲邏輯:實現 TypeHandler 接口,例如將枚舉轉換為特定代碼值。
2. 處理復雜類型
  • JSON 字段:如上述 JsonTypeHandler 示例。
  • 加密字段:自定義處理器,在寫入時加密、讀取時解密敏感數據(如手機號、身份證號)。
3. 處理集合類型
  • 默認支持:MyBatis 內置 ListTypeHandlerMapTypeHandler,但通常直接通過 resultMap 映射集合屬性,無需手動處理。

六、最佳實踐

1. 合理使用類型別名
  • 統一管理:在 mybatis-config.xml 中集中定義別名,避免分散配置。
  • 避免沖突:確保不同包下的類別名唯一,或直接使用全限定類名。
2. 自定義 TypeHandler 的注意事項
  • 線程安全:確保 TypeHandler 無狀態或使用線程安全的數據結構(如上述 ObjectMapper 可復用)。
  • 異常處理:捕獲并轉換異常為 SQLException,避免框架層面崩潰。
3. 性能優化
  • 緩存復雜對象:若頻繁解析 JSON 或加密數據,可添加緩存層(如 ConcurrentHashMap)。
  • 避免過度自定義:優先使用 MyBatis 內置處理器,減少不必要的復雜性。

七、總結

MyBatis 的類型系統通過 類型處理器類型別名 等機制,屏蔽了 Java 對象與數據庫類型之間的差異,使開發者能夠專注于業務邏輯。通過合理使用內置功能并擴展自定義 TypeHandler,可以高效處理復雜數據類型,提升代碼可維護性和靈活性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79254.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79254.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79254.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

新華三H3CNE網絡工程師認證—動態NAT

靜態NAT嚴格地一對一進行地址映射&#xff0c;這就導致即便內網主機長時間離線或者不發送數據時&#xff0c;與之對應的共有地址也處于使用狀態。為了避免地址浪費&#xff0c;動態NAT提出了地址池的概念&#xff1a;所有可用的共用地址組成地址池。 當內部主機訪問外部網絡時臨…

華為OD機試真題 Java 實現【水庫蓄水問題】

前言 博主刷的華為機考題&#xff0c;代碼僅供參考&#xff0c;因為沒有后臺數據&#xff0c;可能有沒考慮到的情況 如果感覺對你有幫助&#xff0c;請點點關注點點贊吧&#xff0c;謝謝你&#xff01; 題目描述 思路 1. 其實就是找一個最大的水坑&#xff0c;兩個…

【Linux】Petalinux驅動開發基礎

基于Petalinux做Linux驅動開發。 部分圖片和經驗來源于網絡,若有侵權麻煩聯系我刪除,主要是做筆記的時候忘記寫來源了,做完筆記很久才寫博客。 專欄目錄:記錄自己的嵌入式學習之路-CSDN博客 目錄 1 一個完整的Linux系統(針對Zynq) 1.1 PS部分 1.2 PL部分(若…

JAVA刷題記錄: 遞歸,搜索與回溯

專題一 遞歸 面試題 08.06. 漢諾塔問題 - 力扣&#xff08;LeetCode&#xff09; class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {dfs(A, B, C, A.size());}public void dfs(List<Integer> a, List<In…

YOLOv11改進:利用RT-DETR主干網絡PPHGNetV2助力輕量化目標檢測

這里寫自定義目錄標題 YOLOv11改進&#xff1a;利用RT-DETR主干網絡PPHGNetV2助力輕量化目標檢測1. 介紹2. 引言3. 技術背景3.1 YOLOv11概述3.2 RT-DETR與PPHGNetV23.3 相關工作 4. 應用使用場景5. 詳細代碼實現5.1 環境準備5.2 PPHGNetV2主干網絡實現5.3 YOLOv11與PPHGNetV2集…

WPF之Button控件詳解

文章目錄 1. 引言2. Button控件基礎Button類定義 3. Button控件的核心屬性3.1 Content屬性3.2 IsDefault屬性3.3 IsCancel屬性3.4 其他常用屬性 4. 按鈕樣式與模板自定義4.1 簡單樣式設置4.2 使用Style對象4.3 觸發器使用4.4 使用ControlTemplate完全自定義4.5 按鈕視覺狀態 5.…

【Java】2025 年 Java 學習路線:從入門到精通

文章目錄 一、Java基礎階段(4-8周)1. 開發環境搭建2. 核心語法基礎3. 面向對象編程(OOP)4. 核心類庫二、Java進階階段(6-10周)1. JVM深度理解2. 并發編程3. 新特性掌握4. 設計模式三、開發框架與中間件(8-12周)1. Spring生態2. 持久層框架3. 常用中間件四、項目實戰階段…

虛幻引擎入門筆記

【虛幻5】UE5新手入門嘗試 虛幻引擎的基礎設置 1.驗證-當文件誤刪的時候&#xff0c;對其進行驗證&#xff0c;可以恢復。 2.虛幻引擎極其強大&#xff0c;可以實現多種復合技能&#xff0c;所在創建項目頁面可以看見不只是創建游戲的項目 3.更改虛幻引擎默認的緩存地址。有些…

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】1.1 數據庫核心概念與PostgreSQL技術優勢

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 深度解析PostgreSQL核心架構與技術優勢&#xff1a;從數據庫原理到實戰場景1.1 數據庫核心概念與PostgreSQL技術優勢1.1.1 關系型數據庫核心架構解析1.1.1.1 數據庫系統的底…

詳解SLAM中的李群和李代數(上)

1 概述 最近閱讀高翔大神的《視覺SLAM十四講》這本書&#xff0c;感覺整本書寫的非常的平實&#xff0c;用非常接地氣的語言毫無保留的介紹了視覺SLAM的相關知識&#xff0c;非常值得一讀。不過&#xff0c;在第4章出現的李群和李代數的相關概念就有點令人難以費解了。其實這段…

libevent庫詳解:高性能異步IO的利器

目錄 一、libevent 簡介 主要特點&#xff1a; 二、事件模型原理 1. event_base 2. event 3. evconnlistener&#xff08;TCP監聽器&#xff09; 4. bufferevent 簡化流程如下&#xff1a; 三、libevent 使用示例 1. 創建事件主循環 2. 創建監聽器&#xff08;TCP&a…

從 “零” 做個開源音樂軟件“SteadyBeat”吧!<1> 準備

換換腦子&#xff0c;做個音樂軟件&#xff0c;根據調性、和弦走向&#xff08;情感&#xff09;、節拍、速度等需求&#xff0c;結合AI和一眾工具&#xff0c;自動生成伴奏、Solo等&#xff0c;有點像庫樂隊&#xff01;自己平時也用得著&#xff0c;暫時取名叫《SteadyBeat》…

npm error code CERT_HAS_EXPIRED

npm error code CERT_HAS_EXPIRED 歡迎來到我的主頁&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就職于醫療科技公司&#xff0c;熱衷分享知識&#xff0c;武漢城市開發者社區主理人 擅長.net、C、python開發&#xff0c; 如果遇到技術問題&#xff0c;即可私…

數字世界的“私人車道“:網絡切片如何用Python搭建專屬通信高速路?

數字世界的"私人車道"&#xff1a;網絡切片如何用Python搭建專屬通信高速路&#xff1f; 2024年6月&#xff0c;中國移動宣布在浙江某智能工廠完成全球首個"5G工業網絡切片"規模商用——這條為生產線定制的"數字專屬車道"&#xff0c;將設備控制…

VSCode Verilog編輯仿真環境搭建

VSCode Verilog環境搭建 下載Iverilog安裝Iverilog驗證安裝VS Code安裝插件 下載Iverilog 官網下載Iverilog 安裝Iverilog 一定要勾選這兩項 建議勾選這兩項 驗證安裝 運行Windows PowerShell輸入命令&#xff1a;iverilog輸入命令&#xff1a;Get-Command gtkwave …

C++ - 數據容器之 list(創建與初始化、元素訪問、容量判斷、元素遍歷、添加元素、刪除元素)

一、創建與初始化 引入 <list> 并使用 std 命名空間 #include <list>using namespace std;創建一個空 list list<int> my_list;創建一個包含 5 個元素&#xff0c;每個元素初始化為 0 的 list list<int> my_list(5);創建一個包含 5 個元素&#xf…

自動化測試項目1 --- 嘮嗑星球 [軟件測試實戰 Java 篇]

目錄 項目介紹 項目源碼庫地址 項目功能測試 1.自動化實施步驟 1.1 編寫測試用例 1.2 自動化測試腳本開發 1.2.1 配置相關環境, 添加相關依賴 1.2.2 相關代碼編寫 2. 自動化功能測試總結 2.1 彈窗的解決相關問題 2.2 斷言的使用和說明 2.3 重新登錄問題 項目性能…

Codeforces Round 1022 (Div. 2)(ABC)

A. Permutation Warm-Up 翻譯&#xff1a; 對于長度為 n 的排列 p&#xff0c;我們定義函數&#xff1a; 給你一個數 n。你需要計算函數 f(p) 在考慮從 1 到 n 的所有可能的數字排列時&#xff0c;可以取多少個不同的值。 思路&#xff1a; 按序排列時和為0&…

數據結構------C語言經典題目(6)

1.數據結構都學了些什么&#xff1f; 1.基本數據類型 算數類型&#xff1a; char&#xff08;字符&#xff09;、int&#xff08;整數&#xff09;、float&#xff08;單精度浮點數&#xff09;、double&#xff08;雙精度浮點數&#xff09;等。 枚舉類型&#xff1a; enum…

如何封裝一個線程安全、可復用的 HBase 查詢模板

目錄 一、前言&#xff1a;原生 HBase 查詢的痛點 &#xff08;一&#xff09;連接管理混亂&#xff0c;容易造成資源泄露 &#xff08;二&#xff09;查詢邏輯重復&#xff0c;缺乏統一的模板 &#xff08;三&#xff09;多線程/高并發下的線程安全性隱患 &#xff08;四…