欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mybatis-plus中更新null值的問題解決

 更新時(shí)間:2024年04月19日 10:42:36   作者:多加點(diǎn)辣也沒關(guān)系  
本文主要介紹 mybatis-plus 中常使用的 update 相關(guān)方法的區(qū)別,以及更新 null 的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

本文主要介紹 mybatis-plus 中常使用的 update 相關(guān)方法的區(qū)別,以及更新 null 的方法有哪些等。

至于為什么要寫這篇文章,首先是在開發(fā)中確實(shí)有被坑過幾次,導(dǎo)致某些字段設(shè)置為 null 值設(shè)置不上,其次是官方文檔對(duì)于這塊內(nèi)容并沒有提供一個(gè)很完善的解決方案,所以我就總結(jié)一下。

一、情景介紹

關(guān)于 Mybatis-plus 這里我就不多做介紹了,如果之前沒有使用過該項(xiàng)技術(shù)的可參考以下鏈接進(jìn)行了解。

mybatis-plus 官方文檔:https://baomidou.com/

在這里插入圖片描述

我們?cè)谑褂?mybatis-plus 進(jìn)行開發(fā)時(shí),默認(rèn)情況下, mybatis-plus 在更新數(shù)據(jù)時(shí)時(shí)會(huì)判斷字段是否為 null,如果是 null 則不設(shè)置值,也就是更新后的該字段數(shù)據(jù)依然是原數(shù)據(jù),雖然說這種方式在一定程度上可以避免數(shù)據(jù)缺失等問題,但是在某些業(yè)務(wù)場(chǎng)景下我們就需要設(shè)置某些字段的數(shù)據(jù)為 null。

二、方法分析

這里我準(zhǔn)備了一個(gè) student 表進(jìn)行測(cè)試分析,該表中僅有兩條數(shù)據(jù):

mysql> SELECT * FROM student;
+-----+---------+----------+
|  id |   name  |   age   |
+-----+---------+----------+
|  1  |  米大傻  |   18    |
+-----+---------+----------+
|  2  |  米大哈  |   20    |
+-----+---------+----------+

在 mybatis-plus 中,我們的 mapper 類都會(huì)繼承 BaseMapper 這樣一個(gè)類

public interface StudentMapper extends BaseMapper<Student> {

}

進(jìn)入到 BaseMapper 這個(gè)接口可以查看到該類僅有兩個(gè)方法和更新有關(guān)(這里我就不去分析 IService 類中的那些更新方法了,因?yàn)槟切┓椒ǖ蛯幼詈笠彩钦{(diào)用了 BaseMapper 中的這兩個(gè) update 方法)

在這里插入圖片描述

所以就從這兩個(gè)方法入手分析:

updateById() 方法

    @Test
    public void testUpdateById() {
        Student student = studentMapper.selectById(1);
        student.setName("李大霄");
        student.setAge(null);
        studentMapper.updateById(student);
    }

在這里插入圖片描述

可以看到使用 updateById() 的方法更新數(shù)據(jù),盡管在代碼中將 age 賦值為 null,但是最后執(zhí)行的 sql 確是:

UPDATE student SET name = '李大霄' WHERE id = 1

也就是說在數(shù)據(jù)庫中,該條數(shù)據(jù)的 name 值發(fā)生了變化,但是 age 保持不變

mysql&gt; SELECT * FROM student WHERE id = 1;
+-----+---------+----------+
|  id |   name  |   age   |
+-----+---------+----------+
|  1  |  李大霄  |   18    |
+-----+---------+----------+

update() 方法 — UpdateWrapper 不設(shè)置屬性

恢復(fù) student 表中的數(shù)據(jù)為初始數(shù)據(jù)。

    @Test
    public void testUpdate() {
        Student student = studentMapper.selectById(1);
        student.setName("李大霄");
        student.setAge(null);
        studentMapper.update(student, new UpdateWrapper<Student>()
                .lambda()
                .eq(Student::getId, student.getId())
        );
    }

在這里插入圖片描述

可以看到如果 update() 方法這樣子使用,效果是和 updateById() 方法是一樣的,為 null 的字段會(huì)直接跳過設(shè)置,執(zhí)行 sql 與上面一樣:

UPDATE student SET name = '李大霄' WHERE id = 1

update() 方法 — UpdateWrapper 設(shè)置屬性

恢復(fù) student 表中的數(shù)據(jù)為初始數(shù)據(jù)。

因?yàn)?nbsp;UpdateWrapper 是可以去字段屬性的,所以再測(cè)試下 UpdateWrapper 中設(shè)置為 null 值是否能起作用

    @Test
    public void testUpdateSet() {
        Student student = studentMapper.selectById(1);
        student.setName("李大霄");
        student.setAge(null);
        studentMapper.update(student, new UpdateWrapper<Student>()
                .lambda()
                .eq(Student::getId, student.getId())
                .set(Student::getAge, student.getAge())
        );
    }

在這里插入圖片描述

從打印的日志信息來看,是可以設(shè)置 null 值的,sql 為:

UPDATE student SET name='李大霄', age=null WHERE id = 1

查看數(shù)據(jù)庫:

mysql> SELECT * FROM student WHERE id = 1;
+-----+---------+----------+
|  id |   name  |   age   |
+-----+---------+----------+
|  1  |  李大霄  |   NULL  |
+-----+---------+----------+

三、原因分析

從方法分析中我們可以得出,如果不使用 UpdateWrapper 進(jìn)行設(shè)置值,通過 BaseMapper 的更新方法是沒法設(shè)置為 null 的,可以猜出 mybatis-plus 在默認(rèn)的情況下就會(huì)跳過屬性為 null 值的字段,不進(jìn)行設(shè)值。

通過查看官方文檔可以看到, mybatis-plus 有幾種字段策略:

在這里插入圖片描述

也就是說在默認(rèn)情況下,字段策略應(yīng)該是 FieldStrategy.NOT_NULL 跳過 null 值的

可以先設(shè)置實(shí)體類的字段更新策略為 FieldStrategy.IGNORED 來驗(yàn)證是否會(huì)忽略判斷 null

@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value="Student對(duì)象", description="學(xué)生表")
public class Student extends BaseEntity {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主鍵ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "姓名")
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 設(shè)置字段策略為:忽略判斷
    private String name;

    @ApiModelProperty(value = "年齡")
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 設(shè)置字段策略為:忽略判斷
    private Integer age;
    
}

再運(yùn)行以上 testUpdateById() 和 testUpdate() 代碼

在這里插入圖片描述

從控制臺(tái)打印的日志可以看出,均執(zhí)行 sql:

UPDATE student SET name='李大霄', age=null WHERE id = 1

所以可知將字段更新策略設(shè)置為: FieldStrategy.IGNORED 就能更新數(shù)據(jù)庫的數(shù)據(jù)為 null 了

翻閱 @TableField 注解的源碼:

在這里插入圖片描述

可以看到在源碼中,如果沒有進(jìn)行策略設(shè)置的話,它默認(rèn)的策略就是 FieldStrategy.DEFAULT 的,那為什么最后處理的結(jié)果是使用了 NOT_NULL 的策略呢?

再追進(jìn)源碼中,可以得知每個(gè)實(shí)體類都對(duì)應(yīng)一個(gè) TableInfo 對(duì)象,而實(shí)體類中每一個(gè)屬性都對(duì)應(yīng)一個(gè) TableFieldInfo 對(duì)象

在這里插入圖片描述

進(jìn)入到 TableFieldInfo 類中查看該類的屬性是有 updateStrategy(修改屬性策略的)

在這里插入圖片描述

查看構(gòu)造方法 TableFieldInfo()

在這里插入圖片描述

可以看到如果字段策略為 FieldStrategy.DEFAULT,取的是 dbConfig.getUpdateStrategy(),如果字段策略不等于 FieldStrategy.DEFAULT,則取注解類 TableField 指定的策略類型。

點(diǎn)擊進(jìn)入對(duì)象 dbConfig 所對(duì)應(yīng)的類 DbConfig 中

在這里插入圖片描述

可以看到在這里 DbConfig 默認(rèn)的 updateStrategy 就是 FieldStrategy.NOT_NULL,所以說 mybatis-plus 默認(rèn)情況下就是跳過 null 值不設(shè)置的。

那為什么通過 UpdateWrapper 的 set 方法就可以設(shè)置值呢?

同樣取查看 set() 方法的源碼:

在這里插入圖片描述

看到這行代碼已經(jīng)明了,因?yàn)榭梢钥吹剿峭ㄟ^ String.format("%s=%s",字段,值) 拼接 sql 的方式,也是是說不管設(shè)置了什么值都會(huì)是 字段=值 的形式,所以就會(huì)被設(shè)置上去。

四、解決方式

從上文分析就可以知道已經(jīng)有兩種方式實(shí)現(xiàn)更新 null ,不過除此之外就是直接修改全局配置,所以這三種方法分別是:

方式一:修改單個(gè)字段策略模式

這種方式在上文已經(jīng)敘述過了,直接在實(shí)體類上指定其修改策略模式即可

@TableField(updateStrategy = FieldStrategy.IGNORED)

在這里插入圖片描述

如果某些字段需要可以在任何時(shí)候都能更新為 null,這種方式可以說是最方便的了。

方式二:修改全局策略模式

通過剛剛分析源碼可知,如果沒有指定字段的策略,取的是 DbConfig 中的配置,而 DbConfig 是 GlobalConfig 的靜態(tài)內(nèi)部類

在這里插入圖片描述

所以我們可以通過修改全局配置的方式,改變 updateStrategy 的策略不就行了嗎?

yml 方式配置如下

mybatis-plus:
  global-config:
    db-config:
      update-strategy: IGNORED

注釋 @TableField(updateStrategy = FieldStrategy.IGNORED)

在這里插入圖片描述

恢復(fù) student 表中的數(shù)據(jù)為初始數(shù)據(jù),進(jìn)行測(cè)試。

在這里插入圖片描述

可以看到是可行的,執(zhí)行的 sql 為:

UPDATE student SET name='李大霄', age=null WHERE id = 1

但是值得注意的是,這種全局配置的方法會(huì)對(duì)所有的字段都忽略判斷,如果一些字段不想要修改,也會(huì)因?yàn)閭鞯氖?null 而修改,導(dǎo)致業(yè)務(wù)數(shù)據(jù)的缺失,所以并不推薦使用。

方式三:使用 UpdateWrapper 進(jìn)行設(shè)置

這種方式前面也提到過了,就是使用 UpdateWrapper 或其子類進(jìn)行 set 設(shè)置,例如:

        studentMapper.update(student, new UpdateWrapper<Student>()
                .lambda()
                .eq(Student::getId, student.getId())
                .set(Student::getAge, null)
                .set(Student::getName, null)
        );

這種方式對(duì)于在某些場(chǎng)合,需要將少量字段更新為 null 值還是比較方便,靈活的。

PS:除此之外還可以通過直接在 mapper.xml 文件中寫 sql,但是我覺得這種方式就有點(diǎn)脫離 mybatis-plus 了,就是 mybatis 的操作,所以就不列其上。

五、方式擴(kuò)展

雖然上面提供了一些方法來更新 null 值,但是不得不說,各有弊端,雖然說是比較推薦使用 UpdateWrapper 來更新 null 值,但是如果在某個(gè)表中,某個(gè)業(yè)務(wù)場(chǎng)景下需要全量更新 null 值,而且這個(gè)表的字段又很多,一個(gè)個(gè) set 真的很折磨人,像 tk.mapper 都有方法進(jìn)行全量更新 null 值,那有沒有什么方法可以全量更新?

雖然 mybaatis-plus 沒有,但是可以自己去實(shí)現(xiàn),我是看了起風(fēng)哥:讓mybatis-plus支持null字段全量更新 這篇博客,覺得蠻好的,所以整理下作此分享。

實(shí)現(xiàn)方式一:使用 UpdateWrapper 循環(huán)拼接 set

提供一個(gè)已 set 好全部字段 UpdateWrapper 對(duì)象的方法:

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();
    }
}

使用:

studentMapper.update(
	WrappersFactory.updateWithNullField(student)
		.eq(Student::getId,id)
);

或者可以定義一個(gè) GaeaBaseMapper(全局 Mapper) 繼承 BaseMapper,所有的類都繼承自 GaeaBaseMapper,例如:

public interface StudentMapper extends GaeaBaseMapper<Student> {

}

編寫 updateWithNullField() 方法:

public interface GaeaBaseMapper<T extends BaseEntity> extends BaseMapper<T> {

    /**
     * 返回全量修改 null 的 updateWrapper
     */
    default LambdaUpdateWrapper<T> updateWithNullField(T entity) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        List<Field> allFields = TableInfoHelper.getAllFields(entity.getClass());
        MetaObject metaObject = SystemMetaObject.forObject(entity);
        allFields.forEach(field -> {
            Object value = metaObject.getValue(field.getName());
            updateWrapper.set(StringUtils.cameToUnderline(field.getName()), value);
        });
        return updateWrapper.lambda();
    }
}

StringUtils.cameToUnderline() 方法

    /**
     * 駝峰命名轉(zhuǎn)下劃線
     * @param str 例如:createUsername
     * @return 例如:create_username
     */
    public static String cameToUnderline(String str) {
        Matcher matcher = Pattern.compile("[A-Z]").matcher(str);
        StringBuilder builder = new StringBuilder(str);
        int index = 0;
        while (matcher.find()) {
            builder.replace(matcher.start() + index, matcher.end() + index, "_" + matcher.group().toLowerCase());
            index++;
        }
        if (builder.charAt(0) == '_') {
            builder.deleteCharAt(0);
        }
        return builder.toString();
    }

使用:

    @Test
    public void testUpdateWithNullField() {
        Student student = studentMapper.selectById(1);
        student.setName("李大霄");
        student.setAge(null);
        studentMapper
                .updateWithNullField(student)
                .eq(Student::getId, student.getId());
    }

實(shí)現(xiàn)方式二:mybatis-plus常規(guī)擴(kuò)展—實(shí)現(xiàn) IsqlInjector

像 mybatis-plus 中提供的批量添加數(shù)據(jù)的 InsertBatchSomeColumn 方法類一樣

在這里插入圖片描述

首先需要定義一個(gè) GaeaBaseMapper(全局 Mapper) 繼承 BaseMapper,所有的類都繼承自 GaeaBaseMapper,例如:

public interface StudentMapper extends GaeaBaseMapper<Student> {

}

然后在這個(gè) GaeaBaseMapper 中添中全量更新 null 的方法

public interface StudentMapper extends GaeaBaseMapper<Student> {

	/**
     * 全量更新null
     */
    int updateWithNull(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
}

構(gòu)造一個(gè)方法 UpdateWithNull 的方法類

public class UpdateWithNull extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        // 處理邏輯
        return null;
    }

}

之前說過可以設(shè)置字段的更新策略屬性為:FieldStrategy.IGNORED 使其可以更新 null 值,現(xiàn)在方法參數(shù)中有 TableInfo 對(duì)象,通過 TableInfo 我們可以拿到所有的 TableFieldInfo,通過反射設(shè)置所有的 TableFieldInfo.updateStrategy 為 FieldStrategy.IGNORED,然后參照 mybatis-plus 自帶的 Update.java 類的邏輯不就行了。

Update.java 源碼:

package com.baomidou.mybatisplus.core.injector.methods;

import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

public class Update extends AbstractMethod {
    public Update() {
    }

    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlMethod sqlMethod = SqlMethod.UPDATE;
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), this.sqlSet(true, true, tableInfo, true, "et", "et."), this.sqlWhereEntityWrapper(true, tableInfo), this.sqlComment());
        SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
        return this.addUpdateMappedStatement(mapperClass, modelClass, this.getMethod(sqlMethod), sqlSource);
    }
}

所以 UpdateWithNull 類中的代碼可以這樣寫:

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.lang.reflect.Field;
import java.util.List;

/**
 * 全量更新 null
 */
public class UpdateWithNull extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {

        // 通過 TableInfo 獲取所有的 TableFieldInfo
        final List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        // 遍歷 fieldList
        for (final TableFieldInfo tableFieldInfo : fieldList) {
            // 反射獲取 TableFieldInfo 的 class 對(duì)象
            final Class<? extends TableFieldInfo> aClass = tableFieldInfo.getClass();
            try {
                // 獲取 TableFieldInfo 類的 updateStrategy 屬性
                final Field fieldFill = aClass.getDeclaredField("updateStrategy");
                fieldFill.setAccessible(true);
                // 將 updateStrategy 設(shè)置為 FieldStrategy.IGNORED
                fieldFill.set(tableFieldInfo, FieldStrategy.IGNORED);
            } catch (final NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        SqlMethod sqlMethod = SqlMethod.UPDATE;
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(),
                this.sqlSet(true, true, tableInfo, true, "et", "et."),
                this.sqlWhereEntityWrapper(true, tableInfo), this.sqlComment());
        SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
        return this.addUpdateMappedStatement(mapperClass, modelClass, this.getMethod(sqlMethod), sqlSource);
    }

    public String getMethod(SqlMethod sqlMethod) {
        return "updateWithNull";
    }

}

再聲明一個(gè) IsqlInjector 繼承 DefaultSqlInjector

public class BaseSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 此 SQL 注入器繼承了 DefaultSqlInjector (默認(rèn)注入器),調(diào)用了 DefaultSqlInjector 的 getMethodList 方法,保留了 mybatis-plus 自帶的方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 批量插入
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        // 全量更新 null
        methodList.add(new UpdateWithNull());
        return methodList;
    }

}

然后在 mybatis-plus 的配置類中將其配置為 spring 的 bean 即可:

@Slf4j
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {

	...

	@Bean
    public BaseSqlInjector baseSqlInjector() {
        return new BaseSqlInjector();
    }

	...
}

我寫的目錄結(jié)構(gòu)大概長(zhǎng)這樣(僅供參考):

在這里插入圖片描述

恢復(fù) student 表中的數(shù)據(jù)為初始數(shù)據(jù),進(jìn)行測(cè)試。

測(cè)試代碼:

    @Test
    public void testUpdateWithNull() {
        Student student = studentMapper.selectById(1);
        student.setName("李大霄");
        student.setAge(null);
        studentMapper.updateWithNull(student,
                new UpdateWrapper<Student>()
                        .lambda()
                        .eq(Student::getId, student.getId())
        );

        student.setName(null);
        student.setAge(18);
        studentMapper.updateById(student);
    }

sql 打印如下:

在這里插入圖片描述

可以看到使用 updateWithNull() 方法更新了 null。

總結(jié)

以上就是我對(duì) mybatis-plus 更新 null 值問題做的探討,結(jié)合測(cè)試實(shí)例與源碼分析,算是解釋得比較明白了,尤其是最后擴(kuò)展的兩種方法自認(rèn)為是比較符合我的需求的,最后擴(kuò)展的那兩種方法都在實(shí)體類 Mapper 和 mybatis-plus 的 BaseMapper 中間多抽了一層 GaeaBaseMapper ,這種方式我是覺得比較推薦的,增加了系統(tǒng)的擴(kuò)展性和靈活性。

擴(kuò)展

MybatisPlus update 更新時(shí)指定要更新為 null 的方法
讓mybatis-plus支持null字段全量更新
Mybatis-Plus中update()和updateById()將字段更新為null
Mybatis-Plus中update更新操作用法
MyBatis-plus源碼解析

到此這篇關(guān)于mybatis-plus中更新null值的問題解決的文章就介紹到這了,更多相關(guān)mybatis-plus 更新null值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽

相關(guān)文章

  • Elasticsearch?percolate?查詢示例詳解

    Elasticsearch?percolate?查詢示例詳解

    這篇文章主要為大家介紹了Elasticsearch?percolate?查詢示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • springboot+vue實(shí)現(xiàn)登錄功能的最新方法整理

    springboot+vue實(shí)現(xiàn)登錄功能的最新方法整理

    最近做項(xiàng)目時(shí)使用到了springboot+vue實(shí)現(xiàn)登錄功能的技術(shù),所以下面這篇文章主要給大家介紹了關(guān)于springboot+vue實(shí)現(xiàn)登錄功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • SpringBoot Maven打包插件spring-boot-maven-plugin無法解析原因

    SpringBoot Maven打包插件spring-boot-maven-plugin無法解析原因

    spring-boot-maven-plugin是spring boot提供的maven打包插件,本文主要介紹了SpringBoot Maven打包插件spring-boot-maven-plugin無法解析原因,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • java對(duì)象初始化順序驗(yàn)證示例

    java對(duì)象初始化順序驗(yàn)證示例

    以下這段小程序?qū)φ{(diào)用對(duì)象構(gòu)造函數(shù)時(shí),父類構(gòu)造函數(shù)、成員變量初始化函數(shù),以及非靜態(tài)初始化塊調(diào)用順序進(jìn)行驗(yàn)證,不考慮靜態(tài)成員及靜態(tài)初始化塊
    2014-02-02
  • Java使用synchronized實(shí)現(xiàn)互斥鎖功能示例

    Java使用synchronized實(shí)現(xiàn)互斥鎖功能示例

    這篇文章主要介紹了Java使用synchronized實(shí)現(xiàn)互斥鎖功能,結(jié)合實(shí)例形式分析了Java使用synchronized互斥鎖功能簡(jiǎn)單實(shí)現(xiàn)方法與操作技巧,需要的朋友可以參考下
    2020-05-05
  • Spring防止重復(fù)點(diǎn)擊的兩種實(shí)現(xiàn)方法

    Spring防止重復(fù)點(diǎn)擊的兩種實(shí)現(xiàn)方法

    頁面重復(fù)提交導(dǎo)致的問題就是數(shù)據(jù)被重復(fù)保存,我們經(jīng)常會(huì)誤觸點(diǎn)擊兩次,所以本文小編給大家介紹了Spring防止重復(fù)點(diǎn)擊的兩種實(shí)現(xiàn)方法,需要的朋友可以參考下
    2025-01-01
  • springboot?@Validated的概念及示例實(shí)戰(zhàn)

    springboot?@Validated的概念及示例實(shí)戰(zhàn)

    這篇文章主要介紹了springboot?@Validated的概念以及實(shí)戰(zhàn),使用?@Validated?注解,Spring?Boot?應(yīng)用可以有效地實(shí)現(xiàn)輸入驗(yàn)證,提高數(shù)據(jù)的準(zhǔn)確性和應(yīng)用的安全性,本文結(jié)合實(shí)例給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • 哈希表在算法題目中的實(shí)際應(yīng)用詳解(Java)

    哈希表在算法題目中的實(shí)際應(yīng)用詳解(Java)

    散列表(Hash?table,也叫哈希表)是根據(jù)關(guān)鍵碼值(Key?value)而直接進(jìn)行訪問的數(shù)據(jù)結(jié)構(gòu),下面這篇文章主要給大家介紹了關(guān)于哈希表在算法題目中的實(shí)際應(yīng)用,文中介紹的方法是Java,需要的朋友可以參考下
    2024-03-03
  • 使用Spring?Cloud?Stream處理Java消息流的操作流程

    使用Spring?Cloud?Stream處理Java消息流的操作流程

    Spring?Cloud?Stream是一個(gè)用于構(gòu)建消息驅(qū)動(dòng)微服務(wù)的框架,能夠與各種消息中間件集成,如RabbitMQ、Kafka等,今天我們來探討如何使用Spring?Cloud?Stream來處理Java消息流,需要的朋友可以參考下
    2024-08-08
  • SpringCloud組件之Eureka Server詳細(xì)啟動(dòng)過程及說明

    SpringCloud組件之Eureka Server詳細(xì)啟動(dòng)過程及說明

    這篇文章主要介紹了SpringCloud組件之Eureka Server詳細(xì)啟動(dòng)過程及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論