您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何在java中使用BeanUtils.copyProperties,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
提起對象轉換,每個程序員都不陌生,比如項目中經常涉及到的DO、DTO、VO之間的轉換,舉個例子,假設現在有個OrderDTO,定義如下所示:
public class OrderDTO { private long id; private Long userId; private String orderNo; private Date gmtCreated; // 省略get、set方法 }
有個OrderVO,定義如下所示:
public class OrderVO { private long id; private long userId; private String orderNo; private Date gmtCreated; // 省略get、set方法 }
如果不使用任何轉換工具,代碼是下面這樣的:
public static void main(String[] args) { OrderDTO orderDTO = new OrderDTO(); orderDTO.setId(1L); orderDTO.setUserId(123L); orderDTO.setOrderNo("20210518000001"); orderDTO.setGmtCreated(new Date()); OrderVO orderVO = new OrderVO(); orderVO.setId(orderDTO.getId()); orderVO.setUserId(orderDTO.getUserId()); orderVO.setOrderNo(orderDTO.getOrderNo()); orderVO.setGmtCreated(orderDTO.getGmtCreated()); System.out.println(orderVO.getId()); System.out.println(orderVO.getUserId()); System.out.println(orderVO.getOrderNo()); System.out.println(orderVO.getGmtCreated()); }
運行結果:
因為項目中類似上面的轉換多而繁瑣,所以很多公司的項目中會使用Spring框架里的BeanUtils.copyProperties來做對象轉換,代碼如下所示:
OrderVO orderVO = new OrderVO(); BeanUtils.copyProperties(orderDTO, orderVO);
一行代碼搞定,很方便,運行結果也和原來一模一樣。
不過這個工具帶來便利的同時,也帶來了很多問題,稍微不注意就會踩坑,接下來就總結下使用這個工具常見的幾個坑。
java.lang.IllegalArgumentException
細心的你可能會發現,OrderDTO中的userId字段,我定義的是Long類型:
而OrderVO中的userId字段,我定義的是long類型:
然后我們運行下下面所示的代碼:
public static void main(String[] args) { OrderDTO orderDTO = new OrderDTO(); orderDTO.setId(1L); orderDTO.setUserId(null); orderDTO.setOrderNo("20210518000001"); orderDTO.setGmtCreated(new Date()); OrderVO orderVO = new OrderVO(); BeanUtils.copyProperties(orderDTO, orderVO); }
會看到代碼拋了java.lang.IllegalArgumentException
異常:
假設OrderVO的orderNo字段,是用戶自定義的,用戶不小心輸入了空格,使用BeanUtils.copyProperties后,空格會帶入到OrderDTO的orderNo字段,如果不小心,就會把臟數據落到數據庫(而我們希望的是去除空格再落庫的),造成一系列后續問題:
public static void main(String[] args) { OrderVO orderVO = new OrderVO(); orderVO.setId(1L); orderVO.setUserId(123L); // 模擬空格場景 orderVO.setOrderNo(" 20210518000001 "); orderVO.setGmtCreated(new Date()); OrderDTO orderDTO = new OrderDTO(); BeanUtils.copyProperties(orderVO, orderDTO); System.out.println(orderDTO.getOrderNo()); }
運行結果:
使用BeanUtils.copyProperties后,會看到字段并沒有引用,其實是有用到的,如下圖所示:
有些小伙伴在看代碼時,看到字段沒有地方引用,可能就忍不住想刪掉,結果就導致真正使用該字段的地方取不到值,產生bug。
如果接口定義的比較嚴謹,理論上是不應該存在這種情況的,不過凡事總有特殊,這里舉個接口不嚴謹導致數據被覆蓋的例子。
假如OrderVO和OrderDTO有如下2個字段:
/** * 已收金額 * 單位:分 */ private Long receivedAmount; /** * 備注 */ private String remark;
正常情況下,后端只應該使用前端傳遞的remark字段,receivedAmount字段不應該使用,但假如用戶修改訂單備注時,前端不小心傳遞了receivedAmount字段,并且賦值為null,這時使用BeanUtils.copyProperties后,OrderDTO里的receivedAmount字段就也為null,如果后端不知道前端傳遞了這個字段并且操作DB不夠嚴謹,就會導致訂單的已收金額被清空,很恐怖,而且不好排查原因。
雖然BeanUtils.copyProperties
工具提供了便利,但帶來的問題也很多,因此很多公司(包含我現在所在的公司)都禁止在項目中使用該工具。
但重復的寫對象轉換,實在是太繁瑣,效率太低了,這里推薦一個IDEA的插件GenerateAllSetter,可以一鍵生成對象的set方法,非常方便,如下圖所示:
插件使用:
在需要生成set方法的對象上,按快捷鍵Option+Enter(Windows是Alt+Enter),會看到下圖所示的選項:
點擊后會自動生成所有字段(沒有默認值)的賦值語句:
如果生成賦值語句時想帶默認值,可以使用另一個選項:
效果如下所示:
上述內容就是如何在java中使用BeanUtils.copyProperties,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。