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

使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決

 更新時(shí)間:2024年07月03日 14:54:41   作者:氵奄不死的魚  
這篇文章主要介紹了使用lombok注解導(dǎo)致mybatis-plus TypeHandler失效的解決,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

問題描述

建立實(shí)體其中一個(gè)字段為枚舉類

/**
 * @author liuxishan 2023/6/2
 */
@Data
@Builder
@TableName(value = "hot_event",autoResultMap = false)
@EqualsAndHashCode(callSuper = true)
public class HotEvent extends BaseAuditor {
    @TableId(type = IdType.ASSIGN_ID)
    private String id;
   ············
   ············ 
    /**
     * 創(chuàng)建方式
     */
    @TableField(typeHandler = HotEventCreationMethodHandler.class,jdbcType = JdbcType.INTEGER)
    private CreationMethodEnum creationMethod;

}
public enum CreationMethodEnum {
    SYSTEM(0, "系統(tǒng)導(dǎo)入"),
    MANUAL_CREATE(1, "手動(dòng)導(dǎo)入");

    /**
     * 用于排序
     */
    private Integer value;

    private String msg;

    CreationMethodEnum(Integer value, String msg) {
        this.value = value;
        this.msg = msg;
    }

    public Integer getValue() {
        return value;
    }

    public String getMsg() {
        return msg;
    }

    public static CreationMethodEnum valueOf(int value) {
        for (CreationMethodEnum creationMethodEnum : CreationMethodEnum.values()) {
            if (creationMethodEnum.value.equals(value)) {
                return creationMethodEnum;
            }
        }
        return null;
    }
}

希望數(shù)據(jù)庫存的時(shí)對應(yīng)的數(shù)字

為了和數(shù)據(jù)庫進(jìn)行轉(zhuǎn)換,使用了typeHandler

public class HotEventCreationMethodHandler implements TypeHandler<CreationMethodEnum> {

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, CreationMethodEnum creationMethodEnum, JdbcType jdbcType) throws SQLException {
        preparedStatement.setInt(i,creationMethodEnum.getValue());
    }

    @Override
    public CreationMethodEnum getResult(ResultSet resultSet, String columnName) throws SQLException {
        int anInt = resultSet.getInt(columnName);
        return CreationMethodEnum.valueOf(anInt);
    }

    @Override
    public CreationMethodEnum getResult(ResultSet resultSet, int i) throws SQLException {
        int anInt = resultSet.getInt(i);
        return CreationMethodEnum.valueOf(anInt);
    }

    @Override
    public CreationMethodEnum getResult(CallableStatement callableStatement, int i) throws SQLException {
        int anInt = callableStatement.getInt(i);
        return CreationMethodEnum.valueOf(anInt);
    }
}

測試發(fā)現(xiàn)

 @Test
    public void pageContents() {
      HotEvent hotEvent = HotEvent.builder()
                .eventName("測試事件名稱")
                .eventOverview("測試測試")
                .eventType(EventTypeEnum.FUND)
                .bizId("1245454")
                .creationMethod(CreationMethodEnum.MANUAL_CREATE)
                .publishingTime(LocalDateTime.now())
                .url("http://baidu.com")
                .publishingAgency("機(jī)構(gòu)")
                .build();
        hotEventDao.insert(hotEvent);
        List<HotEvent> hotEvents = hotEventDao.selectList(Wrappers.<HotEvent>lambdaQuery().eq(HotEvent::getCreationMethod, 1));
     
    }

插入/更新typeHandler生效,但是查詢時(shí)在將數(shù)據(jù)庫數(shù)據(jù)映射成java實(shí)體類的時(shí)候報(bào)錯(cuò)

Caused by: java.lang.IllegalArgumentException: No enum constant com.yiyouliao.rivers.content.api.enums.CreationMethodEnum.1
    at java.lang.Enum.valueOf(Enum.java:238)
    at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:49)
    at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:26)
    at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:85)
    ... 67 more

設(shè)置的HotEventCreationMethodHandler并沒有生效

我們知道,在不開啟autoResultMap時(shí),會(huì)導(dǎo)致TableField對于查詢返回的結(jié)果不生效。(對于更新無影響)

因此首先檢查在實(shí)體類注解上已經(jīng)開啟了autoResultMap,仍然是報(bào)錯(cuò)(mybatisPlus會(huì)根據(jù)我們的實(shí)體類的類型,為我們自動(dòng)注入resultMap,注入的resultMap也會(huì)自動(dòng)推斷出需要使用的類型轉(zhuǎn)換器當(dāng)然我們也可以指定)

@TableName(value = "hot_event",autoResultMap = true)

問題排查

網(wǎng)上查了typeHandler失效的原因,大部分都說的是檢查autoResultMap。無奈只能跟源碼進(jìn)行檢查

問題出在查詢結(jié)果后將結(jié)果轉(zhuǎn)換為java實(shí)體類的地方,由DefaultResultSetHandler進(jìn)行處理

關(guān)鍵方法

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSet
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getRowValue(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap, java.lang.String)

在處理一行數(shù)據(jù)是,正常情況是首先創(chuàng)建java實(shí)體對象,然后根據(jù)resultMap的字段映射 進(jìn)行轉(zhuǎn)換

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
   //創(chuàng)建java實(shí)體對象
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
        final MetaObject metaObject = configuration.newMetaObject(rowValue);
        boolean foundValues = this.useConstructorMappings;
        if (shouldApplyAutomaticMappings(resultMap, false)) {
            foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
        }
        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
        foundValues = lazyLoader.size() > 0 || foundValues;
        rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    return rowValue;
}

但是發(fā)現(xiàn)我們在createResultObject這一步就報(bào)錯(cuò)了,

Caused by: java.lang.IllegalArgumentException: No enum constant com.yiyouliao.rivers.content.api.enums.CreationMethodEnum.1

跟進(jìn)去原因就找到了,在創(chuàng)建對象時(shí)

org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createResultObject(org.apache.ibatis.executor.resultset.ResultSetWrapper, org.apache.ibatis.mapping.ResultMap, java.util.List<java.lang.Class<?>>, java.util.List<java.lang.Object>, java.lang.String)
 private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs);
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }

這里有幾種情況。

  • 有對應(yīng)typeHandler處理當(dāng)前類型,由typeHandler根據(jù)resultSet創(chuàng)建
  • 有constructorMappings(構(gòu)造映射)我們沒有設(shè)置
  • 有默認(rèn)無參構(gòu)造,創(chuàng)建一個(gè)空對象,使用resultMap進(jìn)行映射
  • 無默認(rèn)構(gòu)造,那么根據(jù)構(gòu)造函數(shù),自動(dòng)映射(不使用resultMap)進(jìn)行映射

發(fā)現(xiàn)進(jìn)了第四個(gè)處理邏輯導(dǎo)致報(bào)錯(cuò),那么問題就發(fā)現(xiàn)了,是因?yàn)槲覀兊膶?shí)體類沒有默認(rèn)的無參構(gòu)造函數(shù)

問題結(jié)論

回頭檢查實(shí)體類發(fā)現(xiàn)我們加了@Builder注解,會(huì)為實(shí)體類創(chuàng)建構(gòu)造函數(shù),但是也導(dǎo)致實(shí)體類沒有了無參構(gòu)造。

因此加上注解NoArgsConstructor,問題解決

/**
 * @author liuxishan 2023/6/2
 */
@Data
@Builder
@TableName(value = "hot_event",autoResultMap = false)
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class HotEvent extends BaseAuditor {
    @TableId(type = IdType.ASSIGN_ID)
    private String id;
   ············
   ············ 
    /**
     * 創(chuàng)建方式
     */
    @TableField(typeHandler = HotEventCreationMethodHandler.class,jdbcType = JdbcType.INTEGER)
    private CreationMethodEnum creationMethod;

}

Tips

在查詢時(shí)使用Wrappers構(gòu)造查詢條件時(shí),查詢字段是枚舉時(shí),不能直接使用枚舉,需要使用數(shù)據(jù)庫對應(yīng)的值進(jìn)行查詢,因?yàn)閠ypeHandler僅僅處理的是實(shí)體類字段和jdbcType的轉(zhuǎn)換。

  • 錯(cuò)誤寫法
   List<HotEvent> hotEvents = hotEventDao.selectList(
       Wrappers.<HotEvent>lambdaQuery().eq(HotEvent::getCreationMethod, CreationMethodEnum.MANUAL_CREATE)
   );
  • 正確寫法
   List<HotEvent> hotEvents = hotEventDao.selectList(
       Wrappers.<HotEvent>lambdaQuery().eq(HotEvent::getCreationMethod,1)
   );

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

相關(guān)文章

  • Servlet實(shí)現(xiàn)共享數(shù)據(jù)JavaWeb組件的幾種方法

    Servlet實(shí)現(xiàn)共享數(shù)據(jù)JavaWeb組件的幾種方法

    本文將結(jié)合實(shí)例代碼,介紹Servlet實(shí)現(xiàn)共享數(shù)據(jù)JavaWeb組件的幾種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 源碼閱讀之storm操作zookeeper-cluster.clj

    源碼閱讀之storm操作zookeeper-cluster.clj

    這篇文章主要介紹了源碼閱讀之storm操作zookeeper-cluster.clj的相關(guān)內(nèi)容,對其源碼進(jìn)行了簡要分析,具有參考意義,需要的朋友可以了解下。
    2017-10-10
  • Python 字典常用操作之鍵值對的高效數(shù)據(jù)管理

    Python 字典常用操作之鍵值對的高效數(shù)據(jù)管理

    在 Python 的內(nèi)置數(shù)據(jù)結(jié)構(gòu)中,字典(dict)以其靈活、高效和直觀的特性,成為開發(fā)者最常用的工具之一,本文將帶你從零開始,系統(tǒng)掌握 Python字典的基礎(chǔ)知識(shí)與常用操作,感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • Java從數(shù)據(jù)庫中讀取Blob對象圖片并顯示的方法

    Java從數(shù)據(jù)庫中讀取Blob對象圖片并顯示的方法

    這篇文章主要介紹了Java從數(shù)據(jù)庫中讀取Blob對象圖片并顯示的方法,實(shí)例分析了Java讀取數(shù)據(jù)庫中Blob對象圖片的技巧與操作方法,需要的朋友可以參考下
    2015-02-02
  • 兩分鐘解決IntelliJ IDEA中文亂碼問題(推薦)

    兩分鐘解決IntelliJ IDEA中文亂碼問題(推薦)

    這篇文章主要介紹了兩分鐘解決IntelliJ IDEA中文亂碼問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Java創(chuàng)建型設(shè)計(jì)模式之工廠方法模式深入詳解

    Java創(chuàng)建型設(shè)計(jì)模式之工廠方法模式深入詳解

    工廠方法模式(FACTORY METHOD)是一種常用的類創(chuàng)建型設(shè)計(jì)模式,此模式的核心精神是封裝類中變化的部分,提取其中個(gè)性化善變的部分為獨(dú)立類,通過依賴注入以達(dá)到解耦、復(fù)用和方便后期維護(hù)拓展的目的。它的核心結(jié)構(gòu)有四個(gè)角色,分別是抽象工廠、具體工廠、抽象產(chǎn)品、具體產(chǎn)品
    2022-09-09
  • 深入探討Druid動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方式

    深入探討Druid動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方式

    Druid是一個(gè)高性能的實(shí)時(shí)分析數(shù)據(jù)庫,它可以處理大規(guī)模數(shù)據(jù)集的快速查詢和聚合操作,在Druid中,動(dòng)態(tài)數(shù)據(jù)源是一種可以在運(yùn)行時(shí)動(dòng)態(tài)添加和刪除的數(shù)據(jù)源,使用動(dòng)態(tài)數(shù)據(jù)源,您可以在Druid中輕松地處理不斷變化的數(shù)據(jù)集,本文講給大家介紹一下Druid動(dòng)態(tài)數(shù)據(jù)源該如何實(shí)現(xiàn)
    2023-08-08
  • Java中ThreadLocalMap解決Hash沖突的實(shí)現(xiàn)方式

    Java中ThreadLocalMap解決Hash沖突的實(shí)現(xiàn)方式

    本文主要介紹了Java中ThreadLocalMap解決Hash沖突的實(shí)現(xiàn)方式,主要方式是使用線性探測法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • java 輸出九九乘法表口訣的代碼

    java 輸出九九乘法表口訣的代碼

    這篇文章主要介紹了java 輸出9*9口訣的代碼,需要的朋友可以參考下
    2017-02-02
  • MyBatis通過代碼配置+XML文件構(gòu)建SqlSessionFactory實(shí)踐

    MyBatis通過代碼配置+XML文件構(gòu)建SqlSessionFactory實(shí)踐

    本文介紹了在構(gòu)建SqlSessionFactory時(shí),如何在代碼中動(dòng)態(tài)獲取數(shù)據(jù)庫連接參數(shù),并在XML文件中配置映射文件信息,通過示例代碼,展示了如何在Java和XML文件中實(shí)現(xiàn)這些功能,運(yùn)行結(jié)果總結(jié)了整個(gè)過程的實(shí)現(xiàn)效果
    2026-01-01

最新評論

霍林郭勒市| 八宿县| 泰来县| 桃江县| 馆陶县| 德化县| 叙永县| 呼玛县| 林甸县| 保亭| 建宁县| 西乌珠穆沁旗| 钟祥市| 吉林省| 红河县| 北碚区| 浪卡子县| 正安县| 嵊州市| 云龙县| 峨山| 治多县| 青铜峡市| 兴山县| 黄浦区| 宁南县| 泰来县| 十堰市| 衡山县| 嵩明县| 天祝| 通化县| 内黄县| 彰化县| 准格尔旗| 颍上县| 蓬安县| 西宁市| 定西市| 沧州市| 武山县|