《記屬性拷貝的一次坑》

在spring項(xiàng)目中,有多種不同的O,DTO 、DO、VO等等,不同層使用不同的O。在不同層之間傳輸時(shí)可能會(huì)進(jìn)行不同O之間的轉(zhuǎn)化。所以寫對(duì)象之間的轉(zhuǎn)化的代碼是有必要,但又無(wú)聊的,特別是當(dāng)對(duì)象涉及到特別多的屬性。所以牛人們開發(fā)出自動(dòng)生成set和get的插件:generateAllSetter。使用起來(lái)也是比較簡(jiǎn)單的,例如:現(xiàn)在有兩個(gè)Bean,BeanVO和BeanDTO屬性是一致的,都有三個(gè)String類型的屬性,變量名相同。

(以將DTO轉(zhuǎn)VO為例)自動(dòng)生成代碼步驟就是:首先構(gòu)建一個(gè)如下的函數(shù):

private BeanVO toBeanVo(BeanDTO beanDTO) {

}

函數(shù)返回類型是BeanVO,函數(shù)入?yún)⑹荁eanDTO,接著使用組合按鍵: Alt + Enter ,會(huì)彈出來(lái)下面的選項(xiàng):

接著選中就會(huì)自動(dòng)生成代碼:

當(dāng)對(duì)象屬性特別多的時(shí)候且公司要求手寫不能使用對(duì)象拷貝工具類的時(shí)候,這個(gè)插件的價(jià)值就體現(xiàn)出來(lái)了~


當(dāng)公司允許使用對(duì)象拷貝工具類時(shí),為了代碼的簡(jiǎn)潔美化,工具類也是不錯(cuò)的。以spring的BeanUtils為例:

上述方式可以直接改為:

BeanUtils.copyProperties(beanVO, beanDTO);

確實(shí)挺方便的,但這里有一個(gè)坑,當(dāng)beanDTO拷貝到beanVO時(shí),如果beanDTO的某個(gè)屬性是null,且beanVO中也有這個(gè)屬性時(shí),無(wú)論beanVO這個(gè)屬性是否有值,都會(huì)被設(shè)置為null。

以下舉例:


a對(duì)象的address一開始拷貝到c對(duì)象的,第一次輸出也是正常有值的。b對(duì)象的address是null,在將b凱貝到c對(duì)象時(shí),將原來(lái)的值給設(shè)置為b中address了,所以第二次輸出是null。

來(lái)打斷點(diǎn)看一下:斷點(diǎn)處:BeanUtils.copyProperties(b, c);


可以看到整個(gè)拷貝的步驟是,首先獲取C所有的屬性,對(duì)于每一個(gè)屬性都去B中檢索,如果存在則將b對(duì)象中這個(gè)屬性的值,通過(guò)c的set方法寫入到c對(duì)象中。

解決上述問(wèn)題,可以通過(guò)先將a拷貝給b,接著再將b拷貝給c,就不會(huì)出現(xiàn)null覆蓋原有的不為null的屬性了。見圖


當(dāng)然也可以改寫這個(gè)方法,判斷b中的屬性不為null時(shí)再執(zhí)行invoke方法,寫入到c對(duì)象。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容