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

MyBatis自定義TypeHandler如何解決字段映射問題

 更新時間:2023年12月06日 09:01:38   作者:串一串cc  
這篇文章主要介紹了MyBatis自定義TypeHandler如何解決字段映射問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

MyBatis自定義TypeHandler字段映射

小林子:串哥

串一串:干哈啊,又來

小林子:如果MySQL一張表中一個字段存儲的數(shù)據(jù)格式是"1,2,3,4,5",也就是逗號分隔的,我如何能讓別的使用者在無感知的情況下,只用List<Integer>來傳輸和接收?持久層用的MyBatis。你滴明白我的意思嗎?

串一串:不明白

小林子:…

串一串:你知道MyBatis中有一個類叫BaseTypeHandler嗎?這個類可以滿足你的需求。

小林子:具體要怎么做?我有點懵,沒接觸過這個類,它是干嘛的?

串一串:我們來看個例子

創(chuàng)建一張表待用

create table qfant_message.demo (
	id int auto_increment primary key,
	name varchar(10) null,
	hobbies varchar(100) null
);

然后新建一個SpringBoot工程,在工程中引入mybatis-generator,我們使用它來生成Mapper文件,如果不會的話,自行谷歌,這里不做詳細講解,下一篇再說。

在生成Mapper文件之前,我們先定義一個處理字段hobbiesTypeHandler,命名為ListTypeHandler,這里問個問題:為什么不叫HobbiesTypeHandler呢?這樣應該和字段更加貼合啊。

原因是這個Handler不僅僅是能處理hobbies,它可以處理所有相同情況的任何表的任何字段。

這個類繼承自org.apache.ibatis.type.BaseTypeHandler

看下簡化后的內(nèi)容:

public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {

  @Override
  public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
    if (parameter == null) {
      ps.setNull(i, jdbcType.TYPE_CODE);
    } else {
      setNonNullParameter(ps, i, parameter, jdbcType);
    }
  }

  @Override
  public T getResult(ResultSet rs, String columnName) throws SQLException {
    return getNullableResult(rs, columnName);
  }

  @Override
  public T getResult(ResultSet rs, int columnIndex) throws SQLException {
    return getNullableResult(rs, columnIndex);
  }

  @Override
  public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
    return getNullableResult(cs, columnIndex);
  }

  public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

  public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;

  public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;

  public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;

}

我們可以看到,不論是通過哪一個getResult方法獲取數(shù)據(jù),都是去調(diào)用下面的幾個抽象方法,MyBatis幫我們實現(xiàn)了很多常用的類型的Handler,都在org.apache.ibatis.type包里面,截圖看下吧,免得以為在忽悠你

小林子:那這里面有沒有能滿足我這個需求的Handler?如果有的話我就直接用了

串一串:你去看看,這里我說一下怎么重復造輪子

根據(jù)上述內(nèi)容,我們就可以來寫ListTypeHandler了,在寫之前先整理一下思路:

因為我們實體類中hobbies屬性是java.util.List類型的,而數(shù)據(jù)庫表中hobbies字段是varchar類型的,所以我們需要在更新(插入)之前和查詢之后對數(shù)據(jù)進行一次轉(zhuǎn)換

  • 插入之前:將List中的數(shù)據(jù)轉(zhuǎn)換為以逗號分隔的字符串
  • 查詢之后:將逗號分隔的字符串轉(zhuǎn)換為List結(jié)構(gòu)

思路理順了

我們來看看具體的代碼

package cc.kevinlu.handler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import com.qfant.sms.data.model.DemoDO;

@MappedJdbcTypes(value = { JdbcType.VARCHAR })
//① @MappedTypes(value = DemoDO.class)
public class ListTypeHandler extends BaseTypeHandler<List<Integer>> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Integer> parameter, JdbcType jdbcType)
            throws SQLException {
        String d = parameter.stream().map(v -> String.valueOf(v)).collect(Collectors.joining(","));
        ps.setString(i, d);
    }

    @Override
    public List<Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String values = rs.getString(columnName);
        return getResults(values);
    }

    @Override
    public List<Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String values = rs.getString(columnIndex);
        return getResults(values);
    }

    @Override
    public List<Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String values = cs.getString(columnIndex);
        return getResults(values);
    }

    private List<Integer> getResults(String values) {
        if (StringUtils.isNotBlank(values)) {
            String[] data = values.split(",");
            return Arrays.stream(data).mapToInt(v -> Integer.parseInt(v)).boxed().collect(Collectors.toList());
        }
        return new ArrayList<>();
    }
}

然后生成對應的Mapper和DO實體類,剛才說了我們使用的是mybatis-generator,這里直接貼上<table>的相關(guān)配置

<table tableName="demo" domainObjectName="DemoDO" mapperName="DemoMapper"
       enableCountByExample="true"
       enableDeleteByExample="true" enableInsert="true" enableSelectByExample="true"
       enableUpdateByExample="true"
       selectByExampleQueryId="true" enableSelectByPrimaryKey="true">
  <generatedKey column="id" sqlStatement="MySql" identity="true"/>
  <columnOverride column="hobbies" property="hobbies" jdbcType="VARCHAR" javaType="java.util.List"
                  typeHandler="cc.kevinlu.handler.ListTypeHandler"/>
</table>

注意這里我們使用標簽<columnOverride>重寫了column的定義,這里一定要指明javaTypetypeHandler,javaType的目的是讓生成的DemoDO的屬性hobbies聲明為java.util.List,如果不加該字段的話,默認會根據(jù)jdbcType="VARCHAR"生成java.lang.String類型,然后typeHandler指向我們剛創(chuàng)建的ListTypeHandler,這樣在生成DemoMapper.xml的時候,會在對應的字段上加上typeHandler,否則需要我們挨個兒位置的去修改,xml中的內(nèi)容如下:

<insert id="insert" parameterType="cc.kevinlu.data.model.DemoDO">
  <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
    SELECT LAST_INSERT_ID()
  </selectKey>
  insert into demo (name, hobbies)
  values (
  		#{name,jdbcType=VARCHAR},
  		#{hobbies,jdbcType=VARCHAR,typeHandler=com.qfant.sms.handler.ListTypeHandler}
  )
</insert>

小林子:是不是這樣就可以直接使用了?

串一串:你有沒有注意到ListTypeHandler上有一個被注釋掉的注解,把那個注釋打開,然后value指向DO實體類即可,這個注釋的意思是指定該Handler映射的java類,value是一個數(shù)組,可以指定一組映射類,當然也可以不指定。即使指定了,也可以用于其他類型,然后@MappedJdbcTypes映射的是jdbc的類型

小林子:那現(xiàn)在是不是可以測試啦?走一波~

@Resource
private DemoMapper demoMapper;

@Test
public void index() {
  List<DemoDO> data = demoMapper.selectByExample(new DemoDOExample());
  data.forEach(System.out::println);
}

輸出:

Demo1DO [Hash = 3112387, id=1, name=123, hobbies=[1, 2, 3], serialVersionUID=1]
Demo1DO [Hash = 3294608, id=2, name=456, hobbies=[4, 5, 6], serialVersionUID=1]

總結(jié)一下

1.MyBatis之所以能解決MySQL字段和Java屬性之間的匹配,全都依賴于org.apache.ibatis.type.BaseTypeHandler<T>抽象類,在該類中定義了3個獲取結(jié)果的方法、1個更新的方法和4個抽象方法,我們可以自定義該抽象類來實現(xiàn)這個4個抽象方法進行Java類的屬性和表字段的映射,可以做一些相關(guān)的處理。

2.MyBatis在org.apache.ibatis.type包中定義了常用的字段映射Handler,并且在服務啟動的時候會在TypeHandlerRegistry構(gòu)造方法中將其注冊到一個Map中,而TypeHandlerRegistry是在MyBatis的核心類Configuration中進行的實例化

3.自定義的Handler可以全局通用,不受限于某一個字段或某一個Java類

4.在生成Mapper時使用<columnOverride>重寫column聲明,然后需要指定jdbcTypetypeHandler

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Java如何通過Socket實現(xiàn)查詢IP

    詳解Java如何通過Socket實現(xiàn)查詢IP

    在本文中,我們來學習下如何找到連接到服務器的客戶端計算機的IP地址。我們將創(chuàng)建一個簡單的客戶端-服務器場景,讓我們探索用于TCP/IP通信的java.net?API,感興趣的可以了解一下
    2022-10-10
  • Mybatis-Plus查詢投影與查詢條件設置過程

    Mybatis-Plus查詢投影與查詢條件設置過程

    文章介紹了查詢投影、聚合查詢、分組查詢、分頁查詢、排序查詢和查詢條件設置等內(nèi)容,涵蓋了如何使用MyBatis Plus(MP)進行各種查詢操作,包括lambda表達式、范圍匹配、模糊匹配、空判定、包含性匹配、分組、排序等
    2025-11-11
  • IDEA創(chuàng)建Spring?Boot?Web項目完整圖文教程

    IDEA創(chuàng)建Spring?Boot?Web項目完整圖文教程

    在軟件開發(fā)的浩瀚海洋中,SpringBoot以其獨特的魅力和強大的功能,為開發(fā)者開辟了一條通往高效、便捷開發(fā)之路,這篇文章主要介紹了IDEA創(chuàng)建Spring Boot Web項目的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • java中List對象列表實現(xiàn)去重或取出及排序的方法

    java中List對象列表實現(xiàn)去重或取出及排序的方法

    這篇文章主要介紹了關(guān)于java中List對象列表實現(xiàn)去重或取出以及排序的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。
    2017-08-08
  • SpringBoot面試突擊之過濾器和攔截器區(qū)別詳解

    SpringBoot面試突擊之過濾器和攔截器區(qū)別詳解

    過濾器(Filter)和攔截器(Interceptor)都是基于?AOP(Aspect?Oriented?Programming,面向切面編程)思想實現(xiàn)的,用來解決項目中某一類問題的兩種“工具”,但二者有著明顯的差距,接下來我們一起來看
    2022-10-10
  • Java中Json與List、Map、entity的互相轉(zhuǎn)化

    Java中Json與List、Map、entity的互相轉(zhuǎn)化

    在開發(fā)中,Json轉(zhuǎn)換的場景往往也就是那么幾個,本文主要介紹了Java中Json與List、Map、entity的互相轉(zhuǎn)化,具有一定的參考價值,感興趣的可以了解一下
    2022-07-07
  • Applet小應用程序開發(fā)簡介

    Applet小應用程序開發(fā)簡介

    Applet小應用程序開發(fā)簡介 ,用java開發(fā)的小程序,需要的朋友可以參考下
    2012-09-09
  • 升級springboot3之自動配置導入失效問題及解決

    升級springboot3之自動配置導入失效問題及解決

    這篇文章主要介紹了升級springboot3之自動配置導入失效問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • mybatis中使用大于小于等于的正確方法

    mybatis中使用大于小于等于的正確方法

    在mybatis中sql是寫在xml映射文件中的,如果sql中有一些特殊字符的話,在解析xml文件的時候就會被轉(zhuǎn)義,下面我們就一起來看一下大于小于等于是怎么轉(zhuǎn)義的
    2021-04-04
  • Java全面細致講解==和equals的使用

    Java全面細致講解==和equals的使用

    這篇文章主要介紹了Java中==和equals()的區(qū)別,,==可以使用在基本數(shù)據(jù)類型變量和引用數(shù)據(jù)類型變量中,equals()是方法,只能用于引用數(shù)據(jù)類型,需要的朋友可以參考下
    2022-05-05

最新評論

富川| 昆明市| 安吉县| 芜湖县| 荣昌县| 南川市| 遂昌县| 霍山县| 镇宁| 饶阳县| 驻马店市| 涞水县| 三门县| 陵水| 霍林郭勒市| 施秉县| 铜川市| 景宁| 贡山| 新丰县| 灵宝市| 泌阳县| 孝感市| 永嘉县| 三河市| 图们市| 宜宾县| 耿马| 建始县| 时尚| 上思县| 南宫市| 和龙市| 巴青县| 夏邑县| 镇远县| 抚顺县| 营口市| 怀柔区| 阿勒泰市| 新源县|