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

mybatis-plus支持null字段全量更新的兩種方法

 更新時間:2023年02月24日 09:45:16   作者:起風哥  
本文主要介紹了mybatis-plus支持null字段全量更新的兩種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

背景

如果僅僅只是標題所列的目標,那么mybatis-plus 中可以通過設置
mybatis-plus.global-config.db-config.field-strategy=ignored
來忽略null判斷,達到實體字段為null時也可以更新數(shù)據(jù)為null
但是一旦使用了這個策略,就相當于所有業(yè)務代碼都會按照這個策略執(zhí)行。
但是我們的業(yè)務往往需要如下支持
1、支持null字段全部更新
2、支持非null更新
3、支持指定null字段更新

所以單獨設置某一個策略是很難滿足實際的業(yè)務場景,因此我們需要在寫具體業(yè)務代碼的時候能夠根據(jù)需要選擇合適的方式。

mybatis-plus字段的四種策略

  • default 默認的,一般只用于注解里
    • 在全局里代表 NOT_NULL
    • 在注解里代表 跟隨全局
  • ignored 忽略判斷
  • not_empty 非空判斷
  • not_null 非NULL判斷

這四種策略既可以配置全局,也可以在實體的注解上配置,但是,配置之后就是死的玩意,無法動態(tài)。

一般默認情況下都是not_null,如果此時要更新為null,那么用lambdaUpdateWrapper手動設置哪些字段需要更新為null:
如將userName字段更新為null

userService.update(
                Wrappers.lambdaUpdate(user)
                        .set(User::getUserName, null)
                        .eq(User::getId,"0001"));

很顯然字段較少時這個方案還能說的過去,但是我們既有很少字段的情況,也有大批量字段的情況
所以此時使用這種方案很明顯的使用起來非常難受,那么有沒有方案既能支持有值更新,又能支持指定更新,還能
支持全量更新呢?
答案是有的,提供一個最低成本的適配方案如下

方案一

全局設置字段策略為not_null
因為本身LambdaUpdateWrapper 已經(jīng)滿足了單個設置的需求,所以我們在寫個方法把全部字段組裝起來即可,
當然此處的全部字段肯定也不是真的全部字段比如:一些比較特別的字段就不能被更新為null公共的字段創(chuàng)建時間,更新時間,邏輯刪除字段等等。

public class WrappersFactory {

? ? private final static List<String> ignoreList = new ArrayList<>();

? ? static {
? ? ? ? ignoreList.add(CommonField.available);
? ? ? ? ignoreList.add(CommonField.create_time);
? ? ? ? ignoreList.add(CommonField.create_username);
? ? ? ? ignoreList.add(CommonField.update_time);
? ? ? ? ignoreList.add(CommonField.update_username);
? ? ? ? ignoreList.add(CommonField.create_user_code);
? ? ? ? ignoreList.add(CommonField.update_user_code);
? ? ? ? ignoreList.add(CommonField.deleted);
? ? }

? ? public static <T> LambdaUpdateWrapper<T> updateWithNullField(T entity) {
? ? ? ? UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
? ? ? ? List<Field> allFields = TableInfoHelper.getAllFields(entity.getClass());
? ? ? ? MetaObject metaObject = SystemMetaObject.forObject(entity);
? ? ? ? for (Field field : allFields) {
? ? ? ? ? ? if (!ignoreList.contains(field.getName())) {
? ? ? ? ? ? ? ? Object value = metaObject.getValue(field.getName());
? ? ? ? ? ? ? ? updateWrapper.set(StringUtils.camelToUnderline(field.getName()), value);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return updateWrapper.lambda();
? ? }
}

使用

userService.update(WrappersFactory.updateWithNullField(user).eq(User::getId,"0001"));

方案二

此方案采用的是常規(guī)的mybatis-plus擴展
實際就是實現(xiàn) IsqlInjector

定義個方法

public class UpdateWithNull extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        //具體的字段邏輯在這里處理,實際上就是在這里構造一個新的statement
        return null;
    }
}

定義個CommonMapper繼承自BaseMapper,然后讓你的所有Mapper繼承自CommonMapper

public interface CommonMapper <T> extends BaseMapper<T> {

? ? /**
? ? ?* 根據(jù) whereEntity 條件,更新記錄
? ? ?*
? ? ?* @param entity ? ? ? ?實體對象 (set 條件值,可以為 null)
? ? ?* @param updateWrapper 實體對象封裝操作類(可以為 null,里面的 entity 用于生成 where 語句)
? ? ?*/
? ? int updateWithNull(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

}

聲明一個IsqlInjector,然后將其配置為spring的bean即可

public class CustomSqlInjector extends AbstractSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList() {
        return Stream.of(
                new Insert(),
                new Delete(),
                new DeleteByMap(),
                new DeleteById(),
                new DeleteBatchByIds(),
                new Update(),
                new UpdateWithNull(),
                new UpdateById(),
                new SelectById(),
                new SelectBatchByIds(),
                new SelectByMap(),
                new SelectOne(),
                new SelectCount(),
                new SelectMaps(),
                new SelectMapsPage(),
                new SelectObjs(),
                new SelectList(),
                new SelectPage()
        ).collect(toList());
    }
}

 方案二個人認為沒有什么必要,這種擴展方式是為了增加一些mybatis-plus未支持的定式需求。而我們的目標相對簡單,所以使用方案一更高效。

方案二原理介紹

TableFieldInfo#getSqlSet

public String getSqlSet(final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        // 默認: column=
        String sqlSet = column + EQUALS;
        if (StringUtils.isNotEmpty(update)) {
            sqlSet += String.format(update, column);
        } else {
            sqlSet += SqlScriptUtils.safeParam(newPrefix + el);
        }
        sqlSet += COMMA;
        if (fieldFill == FieldFill.UPDATE || fieldFill == FieldFill.INSERT_UPDATE) {
            // 不進行 if 包裹
            return sqlSet;
        }
        return convertIf(sqlSet, newPrefix + property);
    }

可以看到這段代碼的邏輯中有一行fieldFill判斷,為update或者insert_update時不進行if包裹。我們能可以利用這個特性。直接將需要的非公共字段全部設置為FieldFill.UPDATE即可。

final List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        for (final TableFieldInfo tableFieldInfo : fieldList) {
            final Class<? extends TableFieldInfo> aClass = tableFieldInfo.getClass();
            try {
                final Field fieldFill = aClass.getDeclaredField("fieldFill");
                fieldFill.setAccessible(true);
                fieldFill.set(tableFieldInfo, FieldFill.UPDATE);
            } catch (final NoSuchFieldException e) {
                log.error("獲取fieldFill失敗", e);
            } catch (final IllegalAccessException e) {
                log.error("設置fieldFill失敗", e);
            }
        }

所以這里的具體邏輯為

@Slf4j
public class UpdateWithNull extends AbstractMethod {
? ? @Override
? ? public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
? ? ? ? SqlMethod sqlMethod = SqlMethod.UPDATE;

? ? ? ? final List<TableFieldInfo> fieldList = tableInfo.getFieldList();
? ? ? ? for (final TableFieldInfo tableFieldInfo : fieldList) {
? ? ? ? ? ? final Class<? extends TableFieldInfo> aClass = tableFieldInfo.getClass();
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? final Field fieldFill = aClass.getDeclaredField("fieldFill");
? ? ? ? ? ? ? ? fieldFill.setAccessible(true);
? ? ? ? ? ? ? ? fieldFill.set(tableFieldInfo, FieldFill.UPDATE);
? ? ? ? ? ? } catch (final NoSuchFieldException e) {
? ? ? ? ? ? ? ? log.error("獲取fieldFill失敗", e);
? ? ? ? ? ? } catch (final IllegalAccessException e) {
? ? ? ? ? ? ? ? log.error("設置fieldFill失敗", e);
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(),
? ? ? ? ? ? ? ? sqlSet(true, true, tableInfo, true, ENTITY, ENTITY_DOT),
? ? ? ? ? ? ? ? sqlWhereEntityWrapper(true, tableInfo));
? ? ? ? SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
? ? ? ? return addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
? ? }
}

到此這篇關于mybatis-plus支持null字段全量更新的兩種方法的文章就介紹到這了,更多相關mybatis-plus null全量更新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 在攔截器中讀取request參數(shù),解決在controller中無法二次讀取的問題

    在攔截器中讀取request參數(shù),解決在controller中無法二次讀取的問題

    這篇文章主要介紹了在攔截器中讀取request參數(shù),解決在controller中無法二次讀取的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java?注解@PostConstruct的原理及最佳使用場景分析

    Java?注解@PostConstruct的原理及最佳使用場景分析

    @PostConstruct?是?Java?中非常實用的注解,尤其是在?Spring?等框架中,它使得開發(fā)者可以方便地在?Bean?初始化后執(zhí)行額外的操作,本文給大家介紹@PostConstruct?的原理、使用場景及最佳實踐,感興趣的朋友一起看看吧
    2025-04-04
  • SpringBoot配置攔截器的示例

    SpringBoot配置攔截器的示例

    這篇文章主要介紹了SpringBoot配置攔截器的示例,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2020-11-11
  • SpringBoot(十)之郵件服務

    SpringBoot(十)之郵件服務

    這篇文章給大家介紹了SpringBoot郵件服務的相關知識,此文是使用springboot最新版本1.5.3進行開發(fā)的。本文給大家介紹的非常詳細,具有參考借鑒價值,需要的的朋友參考下吧
    2017-05-05
  • Spring Boot 項目發(fā)布到 Tomcat 服務器的操作步驟

    Spring Boot 項目發(fā)布到 Tomcat 服務器的操作步驟

    這篇文章主要介紹了Spring Boot 項目發(fā)布到 Tomcat 服務器的操作步驟,需要的朋友可以參考下
    2017-04-04
  • Java前后端分離項目跨域問題解決方案

    Java前后端分離項目跨域問題解決方案

    本文主要介紹了Java前后端分離項目跨域問題解決方案,其中后端基于SpringBoot,前端使用了jQuery、axios等框架,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • MybatisPlus的IPage失效的問題解決方案

    MybatisPlus的IPage失效的問題解決方案

    這篇文章主要介紹了MybatisPlus的IPage失效的問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • java實現(xiàn)輸出任意整數(shù)的每一位

    java實現(xiàn)輸出任意整數(shù)的每一位

    這篇文章主要介紹了java實現(xiàn)輸出任意整數(shù)的每一位,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java 數(shù)組迭代你會用嗎

    Java 數(shù)組迭代你會用嗎

    Java 數(shù)組是我們學習或工作中常用到的數(shù)據(jù)結構,我們會經(jīng)常寫數(shù)組迭代的代碼,本文介紹三種數(shù)組迭代的方式,感興趣的可以了解一下
    2021-09-09
  • Java導出Excel統(tǒng)計報表合并單元格的方法詳解

    Java導出Excel統(tǒng)計報表合并單元格的方法詳解

    我們在日常編程過程中,總是會碰見導出相關表格信息的需求,所以就讓我們一起來學習一下,這篇文章主要給大家介紹了關于Java導出Excel統(tǒng)計報表合并單元格的相關資料,需要的朋友可以參考下
    2021-10-10

最新評論

阿城市| 洪湖市| 中江县| 广宁县| 岳西县| 嘉黎县| 大余县| 勐海县| 鸡东县| 永平县| 宣武区| 灵寿县| 徐汇区| 安化县| 本溪| 通州市| 潼南县| 阿拉善左旗| 玉环县| 会宁县| 衡阳市| 大足县| 苗栗县| 汤原县| 灌阳县| 锦州市| 凤凰县| 通山县| 湘乡市| 新野县| 忻城县| 仙桃市| 成武县| 祁门县| 虎林市| 临城县| 故城县| 南涧| 洛川县| 当雄县| 沅江市|