最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis TypeHandler自定義類型轉(zhuǎn)換與實(shí)戰(zhàn)案例解析

 更新時間:2026年01月29日 10:57:02   作者:張彥峰ZYF  
本文將介紹MyBatis中TypeHandler的基礎(chǔ)概念,并通過具體的使用案例,展示如何自定義并應(yīng)用TypeHandler以提高數(shù)據(jù)處理的靈活性和可維護(hù)性,感興趣的朋友跟隨小編一起看看吧

在 MyBatis 中,TypeHandler 是用于處理 Java 類型與數(shù)據(jù)庫字段類型之間轉(zhuǎn)換的關(guān)鍵組件。通過自定義 TypeHandler,我們可以實(shí)現(xiàn)更靈活和高效的類型映射,滿足不同項(xiàng)目中的復(fù)雜需求。本文將介紹 MyBatis 中 TypeHandler 的基礎(chǔ)概念,并通過具體的使用案例,展示如何自定義并應(yīng)用 TypeHandler 以提高數(shù)據(jù)處理的靈活性和可維護(hù)性。

一、Mybatis工作原理簡單回顧

(一)Mybatis框架分層

(二)原理分析

MyBatis 是一款優(yōu)秀的持久層框架,其核心原理如:

  1. 配置文件解析:MyBatis 使用 XML 配置文件來描述數(shù)據(jù)庫連接、SQL 映射關(guān)系、緩存等信息。在啟動時,MyBatis 會解析配置文件,將配置信息加載到內(nèi)存中,并構(gòu)建相應(yīng)的對象模型來表示這些配置。
  2. SqlSessionFactory:SqlSessionFactory 是 MyBatis 的核心接口,它是用于創(chuàng)建 SqlSession 的工廠。SqlSessionFactory 是基于配置文件構(gòu)建的,通過讀取配置文件中的信息,創(chuàng)建出 SqlSessionFactory 對象,以供后續(xù)的數(shù)據(jù)庫操作使用。
  3. SqlSession:SqlSession 是 MyBatis 的核心接口之一,它提供了執(zhí)行 SQL 語句、提交事務(wù)、關(guān)閉連接等數(shù)據(jù)庫操作的方法。SqlSession 是基于 SqlSessionFactory 創(chuàng)建的,每個 SqlSession 對象都代表一個對數(shù)據(jù)庫的會話,它提供了對數(shù)據(jù)庫的各種操作方法。
  4. 映射器(Mapper)接口:在 MyBatis 中,我們可以使用接口來定義 SQL 映射關(guān)系,這些接口被稱為映射器(Mapper)接口。映射器接口通過注解或 XML 配置與具體的 SQL 語句進(jìn)行綁定,并提供了對數(shù)據(jù)庫的操作方法。MyBatis 會為這些接口動態(tài)生成實(shí)現(xiàn)類,從而實(shí)現(xiàn)對數(shù)據(jù)庫的訪問。
  5. SQL 語句的解析與執(zhí)行:MyBatis 通過解析映射文件或注解中的 SQL 語句,將其轉(zhuǎn)換為對應(yīng)的數(shù)據(jù)庫操作。它支持動態(tài) SQL,可以根據(jù)條件生成不同的 SQL 語句,從而實(shí)現(xiàn)更靈活的數(shù)據(jù)庫操作。
  6. 參數(shù)處理:MyBatis 提供了對 SQL 語句中參數(shù)的處理支持。它可以根據(jù)參數(shù)的類型、注解或配置文件中的映射規(guī)則,將 Java 對象與 SQL 語句中的參數(shù)進(jìn)行自動轉(zhuǎn)換。
  7. 結(jié)果集映射:MyBatis 支持將查詢結(jié)果映射為 Java 對象。通過配置文件或注解,可以定義查詢結(jié)果與 Java 對象之間的映射關(guān)系,包括屬性名、類型轉(zhuǎn)換、關(guān)聯(lián)關(guān)系等。MyBatis 使用反射機(jī)制將查詢結(jié)果轉(zhuǎn)換為對應(yīng)的 Java 對象。
  8. 一級緩存和二級緩存:MyBatis 提供了緩存機(jī)制來提高數(shù)據(jù)庫訪問的性能。一級緩存是 SqlSession 級別的緩存,它緩存了查詢的結(jié)果對象。二級緩存是全局級別的緩存,它可以被多個 SqlSession 共享,提供了跨會話的緩存功能。
  9. 事務(wù)管理:MyBatis 支持事務(wù)管理,可以通過配置文件或注解來指定事務(wù)的隔離級別、傳播行為以及異?;貪L規(guī)則。在進(jìn)行數(shù)據(jù)庫操作時,MyBatis 會根據(jù)配置的事務(wù)管理方式來開啟、提交或回滾事務(wù),確保數(shù)據(jù)的一致性和完整性。
  10. 插件機(jī)制:MyBatis 提供了插件機(jī)制,可以在 SQL 語句執(zhí)行的前后進(jìn)行攔截和擴(kuò)展。開發(fā)者可以編寫自定義的插件,并在配置文件中注冊,從而對 SQL 的執(zhí)行過程進(jìn)行攔截和增強(qiáng),實(shí)現(xiàn)自定義的功能擴(kuò)展。

MyBatis 的核心原理是基于配置文件和接口定義的,通過解析配置文件、創(chuàng)建工廠、會話管理和數(shù)據(jù)庫操作等步驟來實(shí)現(xiàn)與數(shù)據(jù)庫的交互。它提供了靈活的 SQL 映射、參數(shù)處理、結(jié)果集映射、緩存和事務(wù)管理等功能,讓開發(fā)者能夠方便地進(jìn)行數(shù)據(jù)庫操作。同時,MyBatis 還支持插件機(jī)制,提供了擴(kuò)展性和定制化的能力,使得開發(fā)者能夠根據(jù)具體需求進(jìn)行功能的增強(qiáng)和定制。

二、TypeHandler自定義轉(zhuǎn)換類型介紹

(一)基本介紹

在 Java 開發(fā)中,TypeHandler 是 MyBatis 框架中的一個核心組件,用于實(shí)現(xiàn)數(shù)據(jù)庫與 Java 類型之間的相互轉(zhuǎn)換。它允許開發(fā)人員自定義類型處理器,以滿足特定的業(yè)務(wù)需求。

TypeHandler 的作用是在 MyBatis 執(zhí)行 SQL 查詢或更新操作時,將數(shù)據(jù)庫中的列值轉(zhuǎn)換為 Java 對象,并在將 Java 對象寫入數(shù)據(jù)庫時執(zhí)行相反的轉(zhuǎn)換。它提供了一種靈活且可擴(kuò)展的方式,用于處理數(shù)據(jù)庫類型與 Java 類型之間的映射關(guān)系。

關(guān)鍵特點(diǎn)和使用方式:

  1. 類型轉(zhuǎn)換:TypeHandler 負(fù)責(zé)將數(shù)據(jù)庫中的列值轉(zhuǎn)換為 Java 對象,并將 Java 對象轉(zhuǎn)換為數(shù)據(jù)庫可接受的類型。
  2. 自定義類型處理器:MyBatis 提供了一些默認(rèn)的類型處理器,例如處理整數(shù)、字符串、日期等常見類型。同時,開發(fā)人員可以根據(jù)需要自定義類型處理器,實(shí)現(xiàn)特定類型的轉(zhuǎn)換邏輯。
  3. 注冊類型處理器:自定義的類型處理器需要在 MyBatis 的配置文件中進(jìn)行注冊,以便 MyBatis 在執(zhí)行數(shù)據(jù)庫操作時能夠找到并使用它們。
  4. 支持復(fù)雜類型:TypeHandler 不僅可以處理基本類型,還可以處理復(fù)雜類型,例如枚舉、自定義對象等。
  5. 映射規(guī)則:TypeHandler 的使用是基于映射規(guī)則的,即在 MyBatis 的映射文件中,通過指定列和屬性之間的映射關(guān)系,TypeHandler 才能正確地進(jìn)行類型轉(zhuǎn)換。

(二)注意事項(xiàng)和建議

在 MyBatis 中使用自定義 TypeHandler 進(jìn)行類型轉(zhuǎn)換時,有一些注意事項(xiàng):

  1. 數(shù)據(jù)庫字段與 Java 對象屬性類型的匹配:確保數(shù)據(jù)庫字段的類型與 Java 對象屬性的類型匹配。如果數(shù)據(jù)庫字段的類型與自定義 TypeHandler 處理的 Java 對象類型不一致,可能會導(dǎo)致轉(zhuǎn)換錯誤或數(shù)據(jù)丟失。
  2. 處理 NULL 值:在自定義 TypeHandler 中處理 NULL 值是很重要的??梢酝ㄟ^判斷傳入的參數(shù)或結(jié)果集中的值是否為 NULL,并在處理過程中進(jìn)行相應(yīng)的處理。例如,可以將 NULL 值轉(zhuǎn)換為 Java 對象的默認(rèn)值,或者通過特定的標(biāo)識值來表示 NULL。
  3. 注冊 TypeHandler:確保在 MyBatis 的配置文件中正確注冊自定義的 TypeHandler。如果沒有正確注冊,MyBatis 將無法找到并使用該 TypeHandler,導(dǎo)致類型轉(zhuǎn)換失敗。
  4. 測試和驗(yàn)證:在使用自定義 TypeHandler 進(jìn)行類型轉(zhuǎn)換之前,建議進(jìn)行充分的測試和驗(yàn)證。確保自定義 TypeHandler 能夠正確地將數(shù)據(jù)庫類型轉(zhuǎn)換為相應(yīng)的 Java 對象類型,并且在查詢和更新操作中能夠正常工作。
  5. 了解官方提供的默認(rèn) TypeHandler:MyBatis 提供了一些默認(rèn)的 TypeHandler,用于常見的數(shù)據(jù)類型轉(zhuǎn)換,如字符串、整數(shù)、日期等。在自定義 TypeHandler 之前,建議先查看官方文檔,了解是否已經(jīng)有現(xiàn)成的 TypeHandler 可以滿足你的需求。
  6. 可重用性和擴(kuò)展性:在設(shè)計(jì)自定義 TypeHandler 時,考慮其可重用性和擴(kuò)展性。如果有多個字段需要進(jìn)行相同的類型轉(zhuǎn)換,可以將轉(zhuǎn)換邏輯封裝在一個通用的 TypeHandler 中,并在映射文件中多次引用它。另外,可以通過繼承或組合的方式擴(kuò)展已有的 TypeHandler,以滿足不同的業(yè)務(wù)需求。
  7. 注意線程安全性:自定義 TypeHandler 應(yīng)該是線程安全的,因?yàn)?MyBatis 在多線程環(huán)境下可能會同時使用同一個 TypeHandler 實(shí)例進(jìn)行類型轉(zhuǎn)換。確保在實(shí)現(xiàn)自定義 TypeHandler 時考慮線程安全性,并采取相應(yīng)的線程安全措施,如使用線程局部變量或同步機(jī)制。

根據(jù)具體的業(yè)務(wù)需求,可以根據(jù)以上的指導(dǎo)來創(chuàng)建適合自己的自定義 TypeHandler,并在 MyBatis 中應(yīng)用它。但是如果害怕出錯還是建議直接使用默認(rèn)的來處理即可,相關(guān)不合理的可能就直接通過查詢或插入時進(jìn)行轉(zhuǎn)換了。

三、業(yè)務(wù)使用基本分析展示

(一)自定義TypeHandler實(shí)現(xiàn)類

自定義TypeHandler實(shí)現(xiàn)類,通常有兩種方式:實(shí)現(xiàn)TypeHandler接口;繼承BaseTypeHandler類。以擴(kuò)展BaseTypeHandler類為例,說明如何實(shí)現(xiàn)想要轉(zhuǎn)換成的數(shù)據(jù)庫對象的具體邏輯。

舉例一:枚舉類型的處理

假設(shè)我們有一個訂單實(shí)體類 Order,其中包含一個 Status 枚舉類型的狀態(tài)字段,在數(shù)據(jù)庫中,我們將狀態(tài)字段存儲為一個字符串類型的列,例如 status。

package org.zyf.javabasic.mybatis;
/**
 * @author yanfengzhang
 * @description 訂單實(shí)體類 Order
 * 其中包含一個 Status 枚舉類型
 * @date 2023/5/13  23:34
 */
public enum Status {
    CREATED,
    PROCESSING,
    COMPLETED,
    CANCELLED
}

我們可以使用自定義的 TypeHandler 來實(shí)現(xiàn) Status 枚舉類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。以下是一個示例的 TypeHandler 實(shí)現(xiàn):

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * @author yanfengzhang
 * @description 自定義的 TypeHandler 來實(shí)現(xiàn) Status 枚舉類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換
 * @date 2023/5/13  23:36
 */
public class StatusTypeHandler extends BaseTypeHandler<Status> {
    @Override
    public Status getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 從 ResultSet 中獲取列值
        int data = rs.getInt(columnName);
        // 將列值轉(zhuǎn)換為枚舉對象
        return Status.getEnumById(data);
    }
    @Override
    public Status getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int data = rs.getInt(columnIndex);
        return Status.getEnumById(data);
    }
    @Override
    public Status getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        int data = callableStatement.getInt(columnIndex);
        return Status.getEnumById(data);
    }
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Status status, JdbcType jdbcType) throws SQLException {
        // 將枚舉值的code存儲到數(shù)據(jù)庫中
        preparedStatement.setInt(i, status.getCode());
    }
}

在上述示例中,我們自定義了一個 TypeHandler 類 StatusTypeHandler,用于處理 Status 枚舉類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。我們需要繼承 BaseTypeHandler 并重寫相應(yīng)的方法來實(shí)現(xiàn)轉(zhuǎn)換邏輯。

舉例二: LocalDateTime類型的處理

假設(shè)我們有一個訂單實(shí)體類 Order,其中包含一個 LocalDateTime 類型的創(chuàng)建時間字段,在數(shù)據(jù)庫中,我們將創(chuàng)建時間字段存儲為一個 DATETIME 類型的列,例如 create_time。

我們可以使用自定義的 TypeHandler 來實(shí)現(xiàn) LocalDateTime 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。以下是一個示例的 TypeHandler 實(shí)現(xiàn):

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
/**
 * @author yanfengzhang
 * @description 自定義的 TypeHandler 來實(shí)現(xiàn) LocalDateTime 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換
 * @date 2023/5/14  10:28
 */
public class LocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException {
        // 將 LocalDateTime 轉(zhuǎn)換為 Timestamp 并設(shè)置到 PreparedStatement 中
        ps.setTimestamp(i, Timestamp.valueOf(parameter));
    }
    @Override
    public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 從 ResultSet 中獲取 Timestamp 值
        Timestamp timestamp = rs.getTimestamp(columnName);
        // 將 Timestamp 轉(zhuǎn)換為 LocalDateTime
        return timestamp != null ? timestamp.toLocalDateTime() : null;
    }
    @Override
    public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Timestamp timestamp = rs.getTimestamp(columnIndex);
        return timestamp != null ? timestamp.toLocalDateTime() : null;
    }
    @Override
    public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Timestamp timestamp = cs.getTimestamp(columnIndex);
        return timestamp != null ? timestamp.toLocalDateTime() : null;
    }
}

在上述示例中,我們自定義了一個 TypeHandler 類 LocalDateTimeTypeHandler,用于處理 LocalDateTime 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。我們需要繼承 BaseTypeHandler 并重寫相應(yīng)的方法來實(shí)現(xiàn)轉(zhuǎn)換邏輯。

現(xiàn)在,當(dāng)使用 MyBatis 進(jìn)行數(shù)據(jù)庫查詢時,會自動將數(shù)據(jù)庫中的列值轉(zhuǎn)換為對應(yīng)的 LocalDateTime 對象,使我們能夠方便地在 Java 代碼中使用 LocalDateTime 類型。

舉例三: List<String> 類型的處理

當(dāng)處理 List 類型時,可以使用自定義的 TypeHandler 將 List 對象轉(zhuǎn)換為字符串進(jìn)行存儲,或者從數(shù)據(jù)庫中讀取字符串并還原為 List 對象。

假設(shè)有一個訂單實(shí)體類 Order,其中包含一個 List<String> 類型的商品列表字段(products),我們可以使用自定義的 TypeHandler 來實(shí)現(xiàn) List<String> 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。以下是一個示例的 TypeHandler 實(shí)現(xiàn):

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
 * @author yanfengzhang
 * @description 自定義的 TypeHandler 來實(shí)現(xiàn) List<String> 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換
 * @date 2023/5/14  10:39
 */
public class StringListTypeHandler extends BaseTypeHandler<List<String>> {
    private static final String DELIMITER = ",";
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        // 將 List<String> 轉(zhuǎn)換為以逗號分隔的字符串
        String rolesString = String.join(DELIMITER, parameter);
        // 將字符串存儲到數(shù)據(jù)庫中
        ps.setString(i, rolesString);
    }
    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 從 ResultSet 中獲取字符串值
        String rolesString = rs.getString(columnName);
        // 將字符串轉(zhuǎn)換為 List<String>
        return parseRolesString(rolesString);
    }
    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String rolesString = rs.getString(columnIndex);
        return parseRolesString(rolesString);
    }
    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String rolesString = cs.getString(columnIndex);
        return parseRolesString(rolesString);
    }
    private List<String> parseRolesString(String rolesString) {
        if (rolesString == null || rolesString.isEmpty()) {
            return Collections.emptyList();
        }
        // 將字符串按逗號分隔轉(zhuǎn)換為 List<String>
        return Arrays.asList(rolesString.split(DELIMITER));
    }
}

在上述示例中,我們自定義了一個 TypeHandler 類 StringListTypeHandler,用于處理 List<String> 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。我們需要繼承 BaseTypeHandler 并重寫相應(yīng)的方法來實(shí)現(xiàn)轉(zhuǎn)換邏輯?,F(xiàn)在,當(dāng)使用 MyBatis 進(jìn)行數(shù)據(jù)庫查詢時,會自動將數(shù)據(jù)庫中的列值轉(zhuǎn)換為對應(yīng)的 List<String> 對象,使我們能夠方便地在 Java 代碼中使用 List<String> 類型。

舉例四: List<Long> 類型的處理

同樣的,可以自定義 TypeHandler 中將 VARCHAR 類型的數(shù)據(jù)庫列與 List<Long> 類型的 Java 對象進(jìn)行轉(zhuǎn)換

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author yanfengzhang
 * @description 自定義 TypeHandler 中將 VARCHAR 類型的數(shù)據(jù)庫列與 List<Long> 類型的 Java 對象進(jìn)行轉(zhuǎn)換
 * @date 2023/5/14  10:48
 */
public class LongListTypeHandler extends BaseTypeHandler<List<Long>> {
    private static final String DELIMITER = ",";
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Long> parameter, JdbcType jdbcType) throws SQLException {
        String joinedString = parameter.stream().map(String::valueOf).collect(Collectors.joining(DELIMITER));
        ps.setString(i, joinedString);
    }
    @Override
    public List<Long> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String columnValue = rs.getString(columnName);
        return convertStringToList(columnValue);
    }
    @Override
    public List<Long> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String columnValue = rs.getString(columnIndex);
        return convertStringToList(columnValue);
    }
    @Override
    public List<Long> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String columnValue = cs.getString(columnIndex);
        return convertStringToList(columnValue);
    }
    private List<Long> convertStringToList(String columnValue) {
        if (columnValue == null || columnValue.isEmpty()) {
            return null;
        }
        List<Long> resultList = new ArrayList<>();
        String[] values = columnValue.split(DELIMITER);
        for (String value : values) {
            resultList.add(Long.valueOf(value));
        }
        return resultList;
    }
}

舉例五:自定義TimePeriod 類型的處理

同樣的,可以自定義 TypeHandler 中將數(shù)據(jù)庫中的時間段(以秒為單位)與 Java 對象中的 TimePeriod 類型進(jìn)行轉(zhuǎn)換。

首先,定義 TimePeriod 類表示時間段:

package org.zyf.javabasic.mybatis;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author yanfengzhang
 * @description
 * @date 2023/5/14  10:58
 */
@Data
public class TimePeriod {
    private LocalDateTime startTime;
    private LocalDateTime endTime;
    public TimePeriod(LocalDateTime startTime, LocalDateTime endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }
}

然后,定義 TimePeriodTypeHandler 類實(shí)現(xiàn) TypeHandler 接口來處理 TimePeriod 類型的轉(zhuǎn)換:

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDateTime;
/**
 * @author yanfengzhang
 * @description 自定義 TypeHandler 中將數(shù)據(jù)庫中的時間段(以秒為單位)與 Java 對象中的 TimePeriod 類型進(jìn)行轉(zhuǎn)換
 * @date 2023/5/14  10:52
 */
public class TimePeriodTypeHandler implements TypeHandler<TimePeriod> {
    @Override
    public void setParameter(PreparedStatement ps, int i, TimePeriod parameter, JdbcType jdbcType) throws SQLException {
        // 將 Java 對象轉(zhuǎn)換為數(shù)據(jù)庫類型,并設(shè)置到 PreparedStatement 中的指定參數(shù)位置
        if (parameter != null) {
            ps.setTimestamp(i, Timestamp.valueOf(parameter.getStartTime()));
            ps.setTimestamp(i + 1, Timestamp.valueOf(parameter.getEndTime()));
        } else {
            ps.setNull(i, Types.TIMESTAMP);
            ps.setNull(i + 1, Types.TIMESTAMP);
        }
    }
    @Override
    public TimePeriod getResult(ResultSet rs, String columnName) throws SQLException {
        // 從 ResultSet 中獲取指定列名的數(shù)據(jù)庫值,并將其轉(zhuǎn)換為對應(yīng)的 Java 對象
        LocalDateTime startTime = rs.getTimestamp(columnName).toLocalDateTime();
        LocalDateTime endTime = rs.getTimestamp(columnName + "_end").toLocalDateTime();
        return new TimePeriod(startTime, endTime);
    }
    @Override
    public TimePeriod getResult(ResultSet rs, int columnIndex) throws SQLException {
        // 從 ResultSet 中獲取指定列索引的數(shù)據(jù)庫值,并將其轉(zhuǎn)換為對應(yīng)的 Java 對象
        LocalDateTime startTime = rs.getTimestamp(columnIndex).toLocalDateTime();
        LocalDateTime endTime = rs.getTimestamp(columnIndex + 1).toLocalDateTime();
        return new TimePeriod(startTime, endTime);
    }
    @Override
    public TimePeriod getResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 從 CallableStatement 中獲取指定列索引的數(shù)據(jù)庫值,并將其轉(zhuǎn)換為對應(yīng)的 Java 對象
        LocalDateTime startTime = cs.getTimestamp(columnIndex).toLocalDateTime();
        LocalDateTime endTime = cs.getTimestamp(columnIndex + 1).toLocalDateTime();
        return new TimePeriod(startTime, endTime);
    }
}

舉例六: InetAddress 類型的處理

假設(shè)我們有一個訂單實(shí)體類 Order,其中包含一個 InetAddress 類型的 IP 地址字段,在數(shù)據(jù)庫中,我們將 IP 地址存儲為一個字符串類型的列,例如 ip_address。

我們可以使用自定義的 TypeHandler 來實(shí)現(xiàn) InetAddress 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換。以下是一個示例的 TypeHandler 實(shí)現(xiàn):

package org.zyf.javabasic.mybatis;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * @author yanfengzhang
 * @description 用于處理 InetAddress 類型與數(shù)據(jù)庫列值之間的轉(zhuǎn)換
 * @date 2023/5/14  11:20
 */
public class InetAddressTypeHandler extends BaseTypeHandler<InetAddress> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, InetAddress parameter, JdbcType jdbcType) throws SQLException {
        // 獲取 IP 地址的字符串表示
        String ipAddressString = parameter.getHostAddress();
        // 將字符串存儲到數(shù)據(jù)庫中
        ps.setString(i, ipAddressString);
    }
    @Override
    public InetAddress getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 從 ResultSet 中獲取字符串值
        String ipAddressString = rs.getString(columnName);
        // 將字符串轉(zhuǎn)換為 InetAddress
        return parseIpAddressString(ipAddressString);
    }
    @Override
    public InetAddress getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String ipAddressString = rs.getString(columnIndex);
        return parseIpAddressString(ipAddressString);
    }
    @Override
    public InetAddress getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String ipAddressString = cs.getString(columnIndex);
        return parseIpAddressString(ipAddressString);
    }
    private InetAddress parseIpAddressString(String ipAddressString) {
        try {
            // 將字符串解析為 InetAddress
            return InetAddress.getByName(ipAddressString);
        } catch (UnknownHostException e) {
            // 處理解析錯誤,例如返回默認(rèn)的 IP 地址或拋出異常
            return null;
        }
    }
}

(二)在mapper.xml文件中進(jìn)行反序列化配置

該寫法只對返回此resultMap的查詢語句有效

 <resultMap id="BaseResultMap" type="org.zyf.javabasic.mybatis.domain.Order">
    <id column="id" jdbcType="BIGINT" property="id"/>
    <result column="name" jdbcType="VARCHAR" property="name"/>
    <result column="status" jdbcType="INTEGER" property="status" 
            typeHandler="org.zyf.javabasic.mybatis.StatusTypeHandler" />
    <result column="limit_period" jdbcType="VARCHAR" property="limitPeriod" 
            typeHandler="org.zyf.javabasic.mybatis.TimePeriodHandler"/>
    <result column="create_time" jdbcType="DATETIME" property="createTime"         
            typeHandler="org.zyf.javabasic.mybatis.LocalDateTimeTypeHandler"/>
    <result column="sku_ids" jdbcType="VARCHAR" property="skuIds" 
            typeHandler="org.zyf.javabasic.mybatis.LongListTypeHandler"/>/>
    <result column="products" jdbcType="VARCHAR" property="products"
            typeHandler="org.zyf.javabasic.mybatis.StringListTypeHandler"/>
    <result column="ip_address" jdbcType="VARCHAR" property="ipAddress"
            typeHandler="org.zyf.javabasic.mybatis.InetAddress"/>
    <result column="cname" jdbcType="VARCHAR" property="cname"/>
    <result column="uname" jdbcType="VARCHAR" property="uname"/>
</resultMap>

(三)在mapper.xml文件中進(jìn)行序列化配置

如果希望在寫入數(shù)據(jù)庫的時候,按照指定規(guī)則對寫入對象進(jìn)行序列化,則需要在寫入sql語句處顯式指定typeHandler

<update id="update" parameterType="map"  >
    UPDATE
        <include refid="Table_Name"/>
    SET
        name = #{order.name},
        limit_period = #{order.limitPeriod, typeHandler=org.zyf.javabasic.mybatis.TimePeriodHandlerer},
        sku_ids =#{order.skuIds, typeHandler=org.zyf.javabasic.mybatis.LongListTypeHandler},
        uname = #{order.uname},
        utime = unix_timestamp()
    where id = #{order.id}
</update>

(四)在mybatis的配置文件config.xml中配置typeHandlers

方法一:啟動時會掃描包下的所有文件

<typeHandlers>
        <package name="org.zyf.javabasic.mybatis"/>
</typeHandlers>

方法二:或單個寫入要注冊的TypeHandler

<typeHandlers>
     <typeHandler handler="org.zyf.javabasic.mybatis.TimePeriodHandler"
                  javaType="org.zyf.javabasic.mybatis.TimePeriod"
                  jdbcType="VARCHAR"/>
     <typeHandler handler="org.zyf.javabasic.mybatis.LongListHandler"
                  javaType="java.util.List"
                  jdbcType="VARCHAR"/>
</typeHandlers>

四、總結(jié)

通過本文的介紹,我們深入了解了 MyBatis 中 TypeHandler 的基本概念及其應(yīng)用場景。TypeHandler 作為 MyBatis 中用于處理 Java 類型和數(shù)據(jù)庫字段類型轉(zhuǎn)換的核心機(jī)制,提供了靈活的擴(kuò)展方式。文章中不僅講解了內(nèi)置的 TypeHandler,還展示了如何通過自定義 TypeHandler 解決實(shí)際開發(fā)中的類型轉(zhuǎn)換問題,提升了代碼的可維護(hù)性與可擴(kuò)展性。掌握這一技術(shù)能夠幫助開發(fā)者更加高效地進(jìn)行數(shù)據(jù)映射處理,優(yōu)化 MyBatis 在項(xiàng)目中的使用效果。

參考文章鏈接

  1. Mybatis之工作原理_mybatis 的原理
  2. MyBatis 官方文檔 - TypeHandlers:MyBatis 官方文檔中關(guān)于 TypeHandler 的詳細(xì)說明和使用示例。
  3. MyBatis TypeHandler 使用詳解:一篇博客文章介紹了如何使用 MyBatis 中的 TypeHandler,并提供了詳細(xì)的示例和說明。
  4. MyBatis TypeHandler 的自定義與應(yīng)用:該文章介紹了如何自定義 TypeHandler,并通過示例演示了各種類型轉(zhuǎn)換的場景。
  5. MyBatis 之 TypeHandler 實(shí)現(xiàn)原理:一篇知乎專欄文章,深入解析了 MyBatis 中的 TypeHandler 實(shí)現(xiàn)原理和相關(guān)的核心類。
  6. MyBatis 之 TypeHandler 源碼解析:該文章通過分析 MyBatis 中的 TypeHandler 源碼,解釋了其內(nèi)部工作原理和實(shí)現(xiàn)細(xì)節(jié)。

到此這篇關(guān)于MyBatis TypeHandler自定義類型轉(zhuǎn)換與實(shí)戰(zhàn)案例解析的文章就介紹到這了,更多相關(guān)MyBatis TypeHandler 自定義類型轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于MyBatis模糊查詢的幾種實(shí)現(xiàn)方式

    關(guān)于MyBatis模糊查詢的幾種實(shí)現(xiàn)方式

    在實(shí)際項(xiàng)目中,我們會經(jīng)常對數(shù)據(jù)做一些模糊查詢的操作,這時候就需要利用到 like字段,那么在Mybatis中,有哪些方式可以實(shí)現(xiàn)模糊查詢呢,需要的朋友可以參考下
    2023-05-05
  • Spring?Boot?+?Spring?Batch?實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程

    Spring?Boot?+?Spring?Batch?實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程

    這篇文章主要介紹了Spring?Boot+Spring?Batch實(shí)現(xiàn)批處理任務(wù),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • MyBatis實(shí)現(xiàn)字段加解密的實(shí)踐

    MyBatis實(shí)現(xiàn)字段加解密的實(shí)踐

    為了數(shù)據(jù)安全問題,有時候需要將部分敏感字段加密后再入庫,本文主要介紹了MyBatis實(shí)現(xiàn)字段加解密的實(shí)踐,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • springboot開啟mybatis二級緩存的步驟詳解

    springboot開啟mybatis二級緩存的步驟詳解

    這篇文章給大家介紹了springboot開啟mybatis二級緩存的詳細(xì)步驟,文中通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • java 依賴包引入本地maven庫的實(shí)現(xiàn)示例

    java 依賴包引入本地maven庫的實(shí)現(xiàn)示例

    本文主要介紹了java 依賴包引入本地maven庫的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-12-12
  • 基于OpenCv與JVM實(shí)現(xiàn)加載保存圖像功能(JAVA?圖像處理)

    基于OpenCv與JVM實(shí)現(xiàn)加載保存圖像功能(JAVA?圖像處理)

    openCv有一個名imread的簡單函數(shù),用于從文件中讀取圖像,本文給大家介紹JAVA?圖像處理基于OpenCv與JVM實(shí)現(xiàn)加載保存圖像功能,感興趣的朋友一起看看吧
    2022-01-01
  • SpringBoot之如何指定配置文件啟動

    SpringBoot之如何指定配置文件啟動

    這篇文章主要介紹了SpringBoot之如何指定配置文件啟動問題,具有很好的參考價值,希望對大家有所幫助。
    2023-04-04
  • java中extends與implements的區(qū)別淺談

    java中extends與implements的區(qū)別淺談

    java中extends與implements的區(qū)別淺談,需要的朋友可以參考一下
    2013-03-03
  • Java實(shí)現(xiàn)Excel轉(zhuǎn)化為圖片的代碼詳解

    Java實(shí)現(xiàn)Excel轉(zhuǎn)化為圖片的代碼詳解

    在實(shí)際開發(fā)里,常常存在將Excel表格或特定區(qū)域轉(zhuǎn)換為圖片,以便在其他軟件中使用的需求,在Java開發(fā)中,借助報(bào)表插件能夠輕松實(shí)現(xiàn)將工作表、任意指定區(qū)域以及各種形狀類型轉(zhuǎn)換為圖片,本文將詳細(xì)介紹如何使用Java達(dá)成Excel到圖片的轉(zhuǎn)化,需要的朋友可以參考下
    2025-08-08
  • JVM原理之完整的一次GC流程解讀

    JVM原理之完整的一次GC流程解讀

    這篇文章主要介紹了JVM原理之完整的一次GC流程解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論

佛坪县| 民权县| 贡山| 武强县| 建始县| 化隆| 荣成市| 河北区| 常宁市| 南宫市| 朝阳市| 余干县| 巫溪县| 卓尼县| 洛阳市| 垫江县| 尉氏县| 龙南县| 焦作市| 德格县| 平谷区| 万荣县| 凤城市| 五家渠市| 汾阳市| 新宾| 故城县| 贵阳市| 华阴市| 天镇县| 久治县| 乃东县| 乐清市| 宁德市| 建阳市| 英德市| 湖北省| 光山县| 元氏县| 和龙市| 兰西县|