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

BeanUtils.copyProperties()所有的空值不復(fù)制問題

 更新時(shí)間:2022年06月15日 10:22:04   作者:Garfield_cat_cat  
這篇文章主要介紹了BeanUtils.copyProperties()所有的空值不復(fù)制問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

BeanUtils.copyProperties()所有的空值不復(fù)制

第一種情況

所有為空值的屬性都不copy

直接上代碼吧~

public class UpdateUtil {
    /**
     * 所有為空值的屬性都不copy
     *
     * @param source
     * @param target
     */
    public static void copyNullProperties(Object source, Object target) {
        BeanUtils.copyProperties(source, target, getNullField(source));
    }
    /**
     * 獲取屬性中為空的字段
     *
     * @param target
     * @return
     */
    private static String[] getNullField(Object target) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(target);
        PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
        Set<String> notNullFieldSet = new HashSet<>();
        if (propertyDescriptors.length > 0) {
            for (PropertyDescriptor p : propertyDescriptors) {
                String name = p.getName();
                Object value = beanWrapper.getPropertyValue(name);
                if (Objects.isNull(value)) {
                    notNullFieldSet.add(name);
                }
            }
        }
        String[] notNullField = new String[notNullFieldSet.size()];
        return notNullFieldSet.toArray(notNullField);
    }
    public static void main(String[] args) {
        TopMenuConfigEntity topMenuConfigEntity1 = new TopMenuConfigEntity();
        topMenuConfigEntity1.setWardCode("cat");
        topMenuConfigEntity1.setTitle("animal");
        TopMenuConfigEntity topMenuConfigEntity2 = new TopMenuConfigEntity();
        topMenuConfigEntity2.setWardCode("dog");
        UpdateUtil.copyNullProperties(topMenuConfigEntity2,topMenuConfigEntity1);
        System.out.println(topMenuConfigEntity1.getTitle());
    }
}

執(zhí)行main 方法后,topMenuConfigEntity1的title還是為原來的“animal”值,沒有被topMenuConfigEntity2 的空值覆蓋。

第二種情況

原對(duì)象的屬性有值,復(fù)制時(shí)指定某些字段不復(fù)制

調(diào)BeanUtils的這個(gè)方法

public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
?? ??? ?copyProperties(source, target, null, ignoreProperties);
?? ?}
 public static void main(String[] args) {
        TopMenuConfigEntity topMenuConfigEntity1 = new TopMenuConfigEntity();
        topMenuConfigEntity1.setWardCode("cat");
        topMenuConfigEntity1.setTitle("animal");
        topMenuConfigEntity1.setCreateTime(new Date());
        TopMenuConfigEntity topMenuConfigEntity2 = new TopMenuConfigEntity();
        String[] ignoreArray = new String[]{"title","createTime"};
        BeanUtils.copyProperties(topMenuConfigEntity2,topMenuConfigEntity1,ignoreArray);
        System.out.println("title : "+topMenuConfigEntity2.getTitle() +";createTime :" + topMenuConfigEntity2.getCreateTime());
    }

topMenuConfigEntity2的title 和createTime為null,沒有復(fù)制

BeanUtils.copyProperties()的用法和注意點(diǎn)

屬性為null也會(huì)被復(fù)制,內(nèi)部類不會(huì)復(fù)制過去

BeanUtils提供對(duì)Java反射和自省API的包裝。其主要目的是利用反射機(jī)制對(duì)JavaBean的屬性進(jìn)行處理。我們知道,一個(gè)JavaBean通常包含了大量的屬性,很多情況下,對(duì)JavaBean的處理導(dǎo)致大量get/set代碼堆積,增加了代碼長(zhǎng)度和閱讀代碼的難度。

BeanUtils是這個(gè)包里比較常用的一個(gè)工具類,這里只介紹它的copyProperties()方法。

該方法源碼如下:

public static void copyProperties(Object source, Object target) throws BeansException {
        copyProperties(source, target, (Class)null, (String[])null);
    }
 
public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException {
        copyProperties(source, target, editable, (String[])null);
    }
 
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
        copyProperties(source, target, (Class)null, ignoreProperties);
    }
 
private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties) throws BeansException {
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");
        Class<?> actualEditable = target.getClass();
        if(editable != null) {
            if(!editable.isInstance(target)) {
                throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
            }
 
            actualEditable = editable;
        }
 
        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
        List<String> ignoreList = ignoreProperties != null?Arrays.asList(ignoreProperties):null;
        PropertyDescriptor[] var7 = targetPds;
        int var8 = targetPds.length;
 
        for(int var9 = 0; var9 < var8; ++var9) {
            PropertyDescriptor targetPd = var7[var9];
            Method writeMethod = targetPd.getWriteMethod();
            if(writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
                PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
                if(sourcePd != null) {
                    Method readMethod = sourcePd.getReadMethod();
                    if(readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }
 
                            Object value = readMethod.invoke(source, new Object[0]);
                            if(!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }
 
                            writeMethod.invoke(target, new Object[]{value});
                        } catch (Throwable var15) {
                            throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
                        }
                    }
                }
            }
        }
 
    }

如果你有兩個(gè)具有很多相同屬性的JavaBean,就可以試用該方法將sourse中的屬性copy到target中,如果sourse和target間存在名稱不相同的屬性,則BeanUtils不對(duì)這些屬性進(jìn)行處理,需要程序員手動(dòng)處理。

怎么樣,很方便吧!除BeanUtils外還有一個(gè)名為PropertyUtils的工具類,它也提供copyProperties()方法,作用與 BeanUtils的同名方法十分相似,主要的區(qū)別在于后者提供類型轉(zhuǎn)換功能,即發(fā)現(xiàn)兩個(gè)JavaBean的同名屬性為不同類型時(shí),在支持的數(shù)據(jù)類型范圍內(nèi)進(jìn)行轉(zhuǎn)換,而前者不支持這個(gè)功能,但是速度會(huì)更快一些。

BeanUtils支持的轉(zhuǎn)換類型如下:

* java.lang.BigDecimal   
  
* java.lang.BigInteger   
  
* boolean and java.lang.Boolean   
  
* byte and java.lang.Byte   
  
* char and java.lang.Character   
  
* java.lang.Class   
  
* double and java.lang.Double   
  
* float and java.lang.Float   
  
* int and java.lang.Integer   
  
* long and java.lang.Long   
  
* short and java.lang.Short   
  
* java.lang.String   
  
* java.sql.Date   
  
* java.sql.Time   
  
* java.sql.Timestamp

這里要注意一點(diǎn),java.util.Date是不被支持的,而它的子類java.sql.Date是被支持的。因此如果對(duì)象包含時(shí)間類型的屬性,且希望被轉(zhuǎn)換的時(shí)候,一定要使用java.sql.Date類型。否則在轉(zhuǎn)換時(shí)會(huì)提示argument mistype異常。

現(xiàn)在,還有一個(gè)壞消息:使用BeanUtils的成本驚人地昂貴!我做了一個(gè)簡(jiǎn)單的測(cè)試,BeanUtils所花費(fèi)的時(shí)間要超過取數(shù) 據(jù)、將其復(fù)制到對(duì)應(yīng)的 value對(duì)象(通過手動(dòng)調(diào)用get和set方法),以及通過串行化將其返回到遠(yuǎn)程的客戶機(jī)的時(shí)間總和。所以要小心使用。

注意點(diǎn)一

apache和spring的工具包中都有BeanUtils,使用其中的copyProperties方法可以非常方便的進(jìn)行這些工作,但在實(shí)際應(yīng)用中發(fā)現(xiàn),對(duì)于null的處理不太符合個(gè)人的需要,例如在進(jìn)行修改操作中只需要對(duì)model中某一項(xiàng)進(jìn)行修改,那么一般我們?cè)陧?yè)面上只提交model的ID及需要修改項(xiàng)的值,這個(gè)時(shí)候使用BeanUtils.copyProperties會(huì)將其他的null綁定到pojo中去。

大家可以直接調(diào)用我們加工類的copyPropertiesIgnoreNull()方法即可忽略null值,避免老數(shù)據(jù)被null覆蓋的尷尬。具體代碼如下:

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; 
import java.util.HashSet;
import java.util.Set; 

public class SpringUtil implements ApplicationContextAware {
 
    /** 
     * 當(dāng)前IOC 
     *  
     */  
    private static ApplicationContext applicationContext;  
 
    /** 
     * * 設(shè)置當(dāng)前上下文環(huán)境,此方法由spring自動(dòng)裝配 
     *  
     */  
    @Override  
    public void setApplicationContext(ApplicationContext arg0)  
            throws BeansException {  
        applicationContext = arg0;  
    }  
 
    /** 
     * 從當(dāng)前IOC獲取bean 
     * 
     * @param id 
     * bean的id 
     * @return 
     *
     */  
    public static Object getObject(String id) {  
        Object object = null;  
        object = applicationContext.getBean(id);  
        return object;  
    } 
    
    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
 
        Set<String> emptyNames = new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
 
    public static void copyPropertiesIgnoreNull(Object src, Object target){
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    } 
}

調(diào)用:copyPropertiesIgnoreNull

public class TestBeanUtiles {
? ? public static void main(String[] args) {
? ? ? ? NewPerson newPerson = new NewPerson();
? ? ? ? newPerson.setName("bifuguo");//前臺(tái)用戶更新過的數(shù)據(jù),例如前臺(tái)只修改了用戶名
? ? ? ? //下面我們假設(shè)是從數(shù)據(jù)庫(kù)加載出來的老數(shù)據(jù)
? ? ? ? OldPerson oldPerson = new OldPerson();
? ? ? ? oldPerson.setSex("nv");
? ? ? ? oldPerson.setAge(5);
? ? ? ? //如果我們想把新數(shù)據(jù)更新到老數(shù)據(jù)這個(gè)對(duì)象里面,我們就可以借助BeanUtils.copyProperties()的方法如下:
? ? ? ? //BeanUtils.copyProperties(newPerson, oldPerson);
? ? ? ? SpringUtil.copyPropertiesIgnoreNull(newPerson, oldPerson);
? ? ? ? System.out.println(newPerson.toString());
? ? ? ? System.out.println(oldPerson.toString());
? ? }
}

打印結(jié)果:

NewPerson{name='bifuguo', sex='null', age=0}
OldPerson{name='bifuguo', sex='nv', age=0}

現(xiàn)在就可以看出老數(shù)據(jù)沒有被null覆蓋

注意點(diǎn)二

1.Spring的BeanUtils的CopyProperties方法需要對(duì)應(yīng)的屬性有g(shù)etter和setter方法;

2.如果存在屬性完全相同的內(nèi)部類,但是不是同一個(gè)內(nèi)部類,即分別屬于各自的內(nèi)部類,則spring會(huì)認(rèn)為屬性不同,不會(huì)copy;

3.泛型只在編譯期起作用,不能依靠泛型來做運(yùn)行期的限制;

4.最后,spring和apache的copy屬性的方法源和目的參數(shù)的位置正好相反,所以導(dǎo)包和調(diào)用的時(shí)候都要注意一下。

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

相關(guān)文章

  • 使用Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類

    使用Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類

    這篇文章主要介紹了使用Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中ArrayList在foreach里remove的問題詳析

    Java中ArrayList在foreach里remove的問題詳析

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList在foreach里remove問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧
    2018-09-09
  • 如何自定義springboot-starter日志組件供各個(gè)服務(wù)使用(系統(tǒng)日志優(yōu)化)

    如何自定義springboot-starter日志組件供各個(gè)服務(wù)使用(系統(tǒng)日志優(yōu)化)

    文章介紹了如何將各個(gè)微服務(wù)的接口調(diào)用日志邏輯優(yōu)化為一個(gè)可共享的Spring Boot Starter,通過自定義注解和自動(dòng)裝配機(jī)制實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 解決

    解決"XML Parser Error on line 1: 前言中不允許有內(nèi)容"錯(cuò)誤

    解決用windows自帶的記事編輯xml文件后出現(xiàn) "XML Parser Error on line 1: 前言中不允許有內(nèi)容。"的錯(cuò)誤
    2018-02-02
  • Java中Finally關(guān)鍵字

    Java中Finally關(guān)鍵字

    與其他語(yǔ)言的模型相比,finally 關(guān)鍵字是對(duì) Java 異常處理模型的最佳補(bǔ)充。接下來通過本文給大家介紹Java中Finally關(guān)鍵字及finally關(guān)鍵字的使用相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • 一文帶你深入了解Java的自動(dòng)拆裝箱

    一文帶你深入了解Java的自動(dòng)拆裝箱

    Java推出了對(duì)于基本數(shù)據(jù)類型的對(duì)應(yīng)的對(duì)象,將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)象就稱為裝箱,反之則是拆箱,本文主要為大家介紹了Java自動(dòng)拆裝箱的原理與應(yīng)用,需要的可以參考下
    2023-11-11
  • Java排序算法總結(jié)之希爾排序

    Java排序算法總結(jié)之希爾排序

    這篇文章主要介紹了Java排序算法總結(jié)之希爾排序,較為詳細(xì)的分析了希爾排序的原理與java的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-05-05
  • IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法

    IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法

    這篇文章主要給大家介紹了關(guān)于IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-11-11
  • 總結(jié)Java對(duì)象被序列化的兩種方法

    總結(jié)Java對(duì)象被序列化的兩種方法

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Java對(duì)象被序列化的兩種方法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • springboot循環(huán)依賴問題案例代碼及解決辦法

    springboot循環(huán)依賴問題案例代碼及解決辦法

    在 Spring Boot 中,如果兩個(gè)或多個(gè) Bean之間存在循環(huán)依賴(即 Bean A 依賴 Bean B,而 Bean B 又依賴 Bean A),會(huì)導(dǎo)致 Spring 的依賴注入機(jī)制無法正確處理,從而拋出異常,下面給大家介紹springboot循環(huán)依賴問題及其解決辦法,感興趣的朋友一起看看吧
    2025-04-04

最新評(píng)論

新竹市| 禄劝| 深州市| 迁安市| 东阳市| 榆林市| 澄城县| 札达县| 左云县| 金乡县| 伊通| 天津市| 正蓝旗| 当涂县| 射阳县| 黄石市| 那坡县| 剑川县| 平远县| 临沂市| 福州市| 莱州市| 温泉县| 武平县| 同江市| 赤峰市| 古丈县| 互助| 淮安市| 海伦市| 普宁市| 丹阳市| 阳朔县| 闻喜县| 绵竹市| 贵阳市| 会昌县| 彩票| 永靖县| 嘉义市| 金湖县|