在 MyBatis 中,TypeHandler
是實現 Java 類型與數據庫類型雙向轉換 的核心組件。無論是處理基礎數據類型還是復雜的 JSON、枚舉或自定義對象,它都能通過靈活的擴展機制滿足開發需求。本文將通過一個 將數據庫 JSON 字符串轉換為 List<User>
的案例,詳解 TypeHandler 的原理與實踐。
一、TypeHandler 的作用與原理
1. 核心功能
- 類型轉換橋梁:將 Java 對象屬性轉換為 JDBC 參數(如
PreparedStatement
設置值); - 結果集映射:將數據庫查詢結果(如
ResultSet
)轉換為 Java 對象屬性; - 空值處理:統一處理 Java 對象與數據庫字段的
NULL
值邏輯。
2. 應用場景
- 內置類型處理:MyBatis 已支持
String
、Integer
、Date
等常見類型的轉換; - 復雜類型處理:如 JSON 字符串與對象互轉、枚舉值與數據庫標記映射、CSV 字符串與集合轉換等。
二、TypeHandler 的配置與擴展
1. 內置 TypeHandler
MyBatis 默認提供多種 TypeHandler,例如:
StringTypeHandler
:處理VARCHAR
與String
;EnumTypeHandler
:處理枚舉與數據庫標記(如disabled
轉0
);DateTypeHandler
:處理日期類型與TIMESTAMP
的轉換。
2. 自定義 TypeHandler 步驟
- 繼承
BaseTypeHandler
:實現setNonNullParameter
(Java→JDBC)和getNullableResult
(JDBC→Java)方法; - 注冊處理器:
- 全局注冊:在
mybatis-config.xml
中通過<typeHandlers>
標簽配置; - 局部指定:在 Mapper XML 或注解中通過
typeHandler
屬性標記;
- 全局注冊:在
- 應用轉換邏輯:在實體類字段或 SQL 映射中聲明使用自定義 TypeHandler。
三、實戰:FastJson 實現 JSON 字符串與 List 轉換
1. 場景描述
假設數據庫表 user_group
的 users
字段存儲 JSON 字符串,需在 Java 中映射為 List<User>
對象:
CREATE TABLE user_group (id BIGINT PRIMARY KEY,users VARCHAR(2048) -- 存儲格式:[{"id":1,"name":"Alice","age":25},...]
);
2. 實現步驟
① 引入依賴
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version>
</dependency>
② 定義 User 實體
public class User {private Long id;private String name;private Integer age;// getters/setters
}
③ 自定義 TypeHandler
public class ListUserTypeHandler extends BaseTypeHandler<List<User>> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, List<User> users, JdbcType jdbcType) throws SQLException {ps.setString(i, JSON.toJSONString(users)); // Java→JSON字符串}@Overridepublic List<User> getNullableResult(ResultSet rs, String columnName) throws SQLException {String json = rs.getString(columnName);return parseJson(json);}private List<User> parseJson(String json) {return json == null ? null : JSON.parseObject(json, new TypeReference<List<User>>(){});}// 其他重寫方法略...
}
④ 全局注冊 TypeHandler
<!-- mybatis-config.xml -->
<typeHandlers><typeHandler handler="com.example.ListUserTypeHandler" javaType="java.util.List" jdbcType="VARCHAR"/>
</typeHandlers>
⑤ 實體類與 Mapper 映射
public class UserGroup {private Long id;@TableField(typeHandler = ListUserTypeHandler.class)private List<User> users;// getters/setters
}
<!-- UserGroupMapper.xml -->
<select id="selectUserGroup" resultType="UserGroup">SELECT * FROM user_group WHERE id = #{id}
</select>
四、測試與驗證
UserGroup group = sqlSession.selectOne("selectUserGroup", 1L);
System.out.println(group.getUsers());
// 輸出:[User{id=1, name='Alice', age=25}, User{id=2, name='Bob', age=30}]
五、總結與擴展
-
優勢
- 解耦業務與持久化邏輯:將類型轉換代碼集中管理,提升可維護性;
- 支持復雜場景:通過自定義邏輯處理加密數據、多語言字段等特殊需求。
-
擴展方向
- 泛型支持:抽象通用 JSON TypeHandler,通過
TypeReference
適配不同泛型類; - 性能優化:針對高頻轉換類型緩存解析結果,減少重復計算。
- 泛型支持:抽象通用 JSON TypeHandler,通過
通過合理使用 TypeHandler,開發者可以顯著提升 MyBatis 在處理復雜數據類型時的靈活性與代碼整潔度,是高效 ORM 實踐的重要工具。