Mybatis自定義TypeHandler解決特殊類型轉(zhuǎn)換問題詳解
我們知道,Java和MySQL中的數(shù)據(jù)類型是不同的,Java中除了基本數(shù)據(jù)類型,還有對象。
有時候使用MySQL存儲數(shù)據(jù),或者從MySQL中讀取數(shù)據(jù)時,會有一些特殊需求 weary ,比如:
- 將Integer數(shù)組直接存入MySQL,保存為BLOB形式,讀取出來時又是正常的Integer數(shù)組
- 將Integer數(shù)組轉(zhuǎn)換為String,然后存入MySQL,使用varchar類型,讀取出來時又是正常的Integer數(shù)組
這也太難了叭!
解決辦法有兩種:
- Basic Method:Java在存入數(shù)據(jù)之前,或讀取數(shù)據(jù)之后,做手動類型轉(zhuǎn)換
- Clever Method:定義TypeHandler,并在Mybatis對應(yīng)位置指明
關(guān)于第一種方法這里不予贅述,不夠Smart。這里主要講述如何自定義Handler,來解決Java數(shù)據(jù)->MySQL數(shù)據(jù)的特殊類型轉(zhuǎn)換問題grinning
這種Handler不僅方便了我們的數(shù)據(jù)庫操作,還有利于代碼的復(fù)用。
這里以Integer[]數(shù)組的存儲為形如,1,2,3,的varchar字符串為例。
問題示例
我們定義一個role類,與數(shù)據(jù)庫的role表對應(yīng):
public class Role {
private Integer id;
private String name;
private Integer[] accessIds;
private Date createTime;
// ... ignore get and set methods
}
注意到里面有一個accessIds字段,它的類型是Integer[]
數(shù)據(jù)庫設(shè)計:
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`access_ids` varchar(255) DEFAULT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', '測試角色', ',1,2,', '2019-11-14 13:43:14');
自定義Handler類
通過繼承BaseTypeHandler類,重寫其方法,定義一個Integer[]與數(shù)據(jù)庫varchar類型自動轉(zhuǎn)換的Handler類:
/**
* Java Int數(shù)組與MySQL String轉(zhuǎn)換器
* 比如[1,2,3] --> ",1,2,3,"
*/
public class StringToIntArrayHandler extends BaseTypeHandler<Integer[]> {
private static final String splitCharset = ",";
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Integer[] objects, JdbcType jdbcType) throws SQLException {
String str = arrayToString(objects);
ps.setString(i, str);
}
@Override
public Integer[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
String str = rs.getString(columnName);
return stringToArray(str);
}
@Override
public Integer[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String str = rs.getString(columnIndex);
return stringToArray(str);
}
@Override
public Integer[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String str = cs.getString(columnIndex);
return stringToArray(str);
}
// --- private methods ---
/**
* Integer數(shù)組轉(zhuǎn)String
* 注:使用提前設(shè)定好的分隔符分割數(shù)組的每一項(xiàng)
*/
private static String arrayToString(Integer[] array) {
StringBuilder res = new StringBuilder();
if (array != null && array.length > 0) {
for (Object o : array) {
res.append(splitCharset).append(o.toString());
}
res.append(splitCharset);
}
return res.length() > 0 ? res.toString() : null;
}
/**
* 從String轉(zhuǎn)Integer數(shù)組
* 注:String是用分隔符分割的,使用String.split方法可以分解為數(shù)組
*/
private static Integer[] stringToArray(String str) {
List<Integer> list = new ArrayList<>();
if (str != null) {
String[] array = str.split(splitCharset);
if (array.length > 0) {
for (String o : array) {
if (o != null && o.length() > 0) {
list.add(Integer.parseInt(o));
}
}
}
}
return list.toArray(new Integer[0]);
}
}
這個類的具體作用是什么呢?
- 當(dāng)Java中類型是Integer[]時,使用這個Handler類,將Integer[]轉(zhuǎn)換為以,號分割的字符串,然后存入數(shù)據(jù)庫
- 當(dāng)從數(shù)據(jù)庫讀取以,分割值的字符串時,可以通過這個Handler,自動將字符串轉(zhuǎn)換為Integer[]數(shù)組
下面我們演示一下具體的使用smile
在Mybatis中應(yīng)用自定義的Handler
Mybatis存放SQL語句的XML文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.model.dao.RoleDAO">
<resultMap id="roleMap" type="com.example.model.bean.Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="accessIds" column="access_ids"
typeHandler="ccom.example.model.dao.handler.StringToIntArrayHandler"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="findById" parameterType="map" resultMap="roleMap">
SELECT id, name, access_ids, create_time
FROM role
WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.example.model.bean.Role">
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO role
(name, create_time, access_ids)
VALUES
(#{name}, #{createTime}
, #{accessIds, jdbcType=VARCHAR, typeHandler=com.example.model.dao.handler.StringToIntArrayHandler})
</insert>
</mapper>
以上XML中演示了select和insert兩種情況時,如何應(yīng)用typeHandler。
- Mybatis實(shí)現(xiàn)自定義的typehandler三步曲
- MyBatis自定義typeHandler的完整實(shí)例
- MyBatis-Plus如何通過注解使用TypeHandler
- Mybatis實(shí)現(xiàn)自定義類型轉(zhuǎn)換器TypeHandler的方法
- Mybatis中自定義TypeHandler處理枚舉詳解
- Mybatis實(shí)戰(zhàn)之TypeHandler高級進(jìn)階
- Mybatis之類型處理器TypeHandler的作用與自定義方式
- MyBatis使用自定義TypeHandler轉(zhuǎn)換類型的實(shí)現(xiàn)方法
- MyBatis-Plus?中?typeHandler?的使用實(shí)例詳解
- MyBatis中TypeHandler的使用教程詳解
- 一文搞懂MyBatis中TypeHandler機(jī)制
相關(guān)文章
Java實(shí)戰(zhàn)之在線租房系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了利用Java實(shí)現(xiàn)的在線租房系統(tǒng),文中用到了SpringBoot、Redis、MySQL、Vue等技術(shù),文中示例代碼講解詳細(xì),需要的可以參考一下2022-02-02
Java中對AtomicInteger和int值在多線程下遞增操作的測試
這篇文章主要介紹了Java中對AtomicInteger和int值在多線程下遞增操作的測試,本文得出AtomicInteger操作 與 int操作的效率大致相差在50-80倍上下的結(jié)論,需要的朋友可以參考下2014-09-09
SpringBoot中集成screw(螺絲釘)實(shí)現(xiàn)數(shù)據(jù)庫表結(jié)構(gòu)文檔生成方法
這篇文章主要介紹了SpringBoot中集成screw(螺絲釘)實(shí)現(xiàn)數(shù)據(jù)庫表結(jié)構(gòu)文檔生成,下面以連接mysql數(shù)據(jù)庫并生成html格式的數(shù)據(jù)庫結(jié)構(gòu)文檔為例,插件的使用方式除可以使用代碼外,還可以使用Maven插件的方式,需要的朋友可以參考下2024-07-07
Hadoop源碼分析四遠(yuǎn)程debug調(diào)試
本篇是Hadoop源碼分析系列文章第四篇,主要介紹一下Hadoop的遠(yuǎn)程debug調(diào)試步驟,后續(xù)本系列文章會持續(xù)更新,有需要的朋友可以借鑒參考下2021-09-09
IDEA關(guān)閉SpringBoot程序后仍然占用端口的排查與解決方法
在使用 IntelliJ IDEA 開發(fā) Spring Boot 應(yīng)用時,有時即使關(guān)閉了應(yīng)用,程序仍然占用端口,這會導(dǎo)致重新啟動應(yīng)用時出現(xiàn)端口被占用的錯誤,所以本文給大家介紹了IDEA關(guān)閉SpringBoot程序后仍然占用端口的排查與解決方法,需要的朋友可以參考下2025-02-02

