Dozer輕松實現對象間屬性復制

          Dozer

           

          對外接口,一般都使用特定的DTO對象,而不會使用領域模型,以避免兩者的變動互相影響。其他框架適配等情形,也可能需要DTO對象。

           

          如果手工一個個屬性的在兩個對象間復制有點累人,如果對象里面還有對象,就更累了。所以希望有一個工具類,可以一行代碼就把對象A中的屬性全部Copy到對象B中。 普通的反射框架不適合做這個事情,看看Dozer 所支持的特性就知道了:

           

          支持兩個對象間的同一屬性的類型是異構的對象,比如CarDTOengine屬性是EngineDTO Carengine屬性是Engine

           

          支持String <-> 基礎類型的轉換,比如CarDTOprice屬性是String, Carprice屬性是Double.

           

          支持Collection類型間的轉換,比如String[] <-> List

           

          支持雙向依賴,比如Product有個屬性是List parts, 而每個Part也有一個Product屬性,此時ProductPart雙向依賴了。

           

          屬性名實在不一致時,可以用@Mapping定義,而且只在其中一邊定義就可以了。

           

          Dozer 也有個缺點,必須基于getter/setter,不能直接訪問public field,卡住了我讓Entity/DTO都取消掉getter/setter的計劃。

           

          Dozer已比較成熟,所以更新很慢。另一個類似但更新較勤快的項目叫Orika

           

           

          In SpringSide

          core中封裝了一個BeanMapper,實現如下功能:

           

          持有Dozer單例, 避免重復創建DozerMapper消耗資源.

           

          自動泛型類型轉換.

           

          批量轉換Collection中的所有對象.

           

          區分創建新的B對象與將對象A值賦值到已存在的B對象的函數.

           

          showcase中有一個DozerDemo,詳細演示了Dozer上述的各種特性。

           

           

           

          所需jar

           

           1<dependency>

                   <groupId>net.sf.dozer</groupId>

                   <artifactId>dozer</artifactId>

                   <version>5.3.1</version>

                </dependency>

           2<dependency>

                   <groupId>org.springside</groupId>

                   <artifactId>springside-core</artifactId>

                </dependency>

            1 package org.springside.examples.showcase.utilities.dozer;
            2 
            3 import static org.junit.Assert.*;
            4 
            5 import java.util.List;
            6 
            7 import org.dozer.Mapping;
            8 import org.junit.Test;
            9 import org.springside.modules.mapper.BeanMapper;
           10 
           11 /**
           12  * 演示Dozer如何只要屬性名相同,可以罔顧屬性類型是基礎類型<->String的差別,Array轉為List,甚至完全另一種DTO的差別。
           13  * 并且能完美解決循環依賴問題。
           14  * 使用@Mapping能解決屬性名不匹配的情況.
           15  */
           16 public class DozerDemo {
           17 
           18     /**
           19      * 從一個ProductDTO實例,創建出一個新的Product實例。
           20      */
           21     @Test
           22     public void map() {
           23         ProductDTO productDTO = new ProductDTO();
           24         productDTO.setName("car");
           25         productDTO.setPrice("200");
           26 
           27         PartDTO partDTO = new PartDTO();
           28         partDTO.setName("door");
           29         partDTO.setProduct(productDTO);
           30 
           31         productDTO.setParts(new PartDTO[] { partDTO });
           32 
           33         //ProductDTO->Product
           34         Product product = BeanMapper.map(productDTO, Product.class);
           35 
           36         assertEquals("car", product.getProductName());
           37         //原來的字符串被Map成Double。
           38         assertEquals(new Double(200), product.getPrice());
           39         //原來的PartDTO同樣被Map成Part ,Array被Map成List
           40         assertEquals("door", product.getParts().get(0).getName());
           41         //Part中循環依賴的Product同樣被賦值。
           42         assertEquals("car", product.getParts().get(0).getProduct().getProductName());
           43 
           44         //再反向從Product->ProductDTO
           45         ProductDTO productDTO2 = BeanMapper.map(product, ProductDTO.class);
           46         assertEquals("car", productDTO2.getName());
           47         assertEquals("200.0", productDTO2.getPrice());
           48         assertEquals("door", productDTO2.getParts()[0].getName());
           49     }
           50 
           51     /**
           52      * 演示將一個ProductDTO實例的內容,Copy到另一個已存在的Product實例.
           53      */
           54     @Test
           55     public void copy() {
           56         ProductDTO productDTO = new ProductDTO();
           57         productDTO.setName("car");
           58         productDTO.setPrice("200");
           59 
           60         PartDTO partDTO = new PartDTO();
           61         partDTO.setName("door");
           62         partDTO.setProduct(productDTO);
           63 
           64         productDTO.setParts(new PartDTO[] { partDTO });
           65 
           66         //已存在的Product實例
           67         Product product = new Product();
           68         product.setProductName("horse");
           69         product.setWeight(new Double(20));
           70 
           71         BeanMapper.copy(productDTO, product);
           72 
           73         //原來的horse,被替換成car
           74         assertEquals("car", product.getProductName());
           75         //原來的20的屬性被覆蓋成200,同樣被從字符串被專為Double。
           76         assertEquals(new Double(200), product.getPrice());
           77         //DTO中沒有的屬性值,在Product中被保留
           78         assertEquals(new Double(20), product.getWeight());
           79         //Part中循環依賴的Product同樣被賦值。
           80         assertEquals("car", product.getParts().get(0).getProduct().getProductName());
           81     }
           82 
           83     public static class Product {
           84         private String productName;
           85         private Double price;
           86         private List<Part> parts;
           87         //DTO中沒有的屬性
           88         private Double weight;
           89 
           90         public String getProductName() {
           91             return productName;
           92         }
           93 
           94         public void setProductName(String productName) {
           95             this.productName = productName;
           96         }
           97 
           98         public Double getPrice() {
           99             return price;
          100         }
          101 
          102         public void setPrice(Double price) {
          103             this.price = price;
          104         }
          105 
          106         public List<Part> getParts() {
          107             return parts;
          108         }
          109 
          110         public void setParts(List<Part> parts) {
          111             this.parts = parts;
          112         }
          113 
          114         public Double getWeight() {
          115             return weight;
          116         }
          117 
          118         public void setWeight(Double weight) {
          119             this.weight = weight;
          120         }
          121 
          122     }
          123 
          124     public static class Part {
          125         //反向依賴Product
          126         private Product product;
          127 
          128         private String name;
          129 
          130         public String getName() {
          131             return name;
          132         }
          133 
          134         public void setName(String name) {
          135             this.name = name;
          136         }
          137 
          138         public Product getProduct() {
          139             return product;
          140         }
          141 
          142         public void setProduct(Product product) {
          143             this.product = product;
          144         }
          145     }
          146 
          147     public static class ProductDTO {
          148         //定義到Product中的productName,只要在一邊定義,雙向轉換都可以使用.
          149         @Mapping("productName")
          150         private String name;
          151         //類型為String 而非 Double
          152         private String price;
          153         //類型為Array而非List, PartDTO而非Part
          154         private PartDTO[] parts;
          155 
          156         public String getName() {
          157             return name;
          158         }
          159 
          160         public void setName(String name) {
          161             this.name = name;
          162         }
          163 
          164         public String getPrice() {
          165             return price;
          166         }
          167 
          168         public void setPrice(String price) {
          169             this.price = price;
          170         }
          171 
          172         public PartDTO[] getParts() {
          173             return parts;
          174         }
          175 
          176         public void setParts(PartDTO[] parts) {
          177             this.parts = parts;
          178         }
          179     }
          180 
          181     public static class PartDTO {
          182         //反向依賴ProductDTO
          183         private ProductDTO product;
          184 
          185         private String name;
          186 
          187         public String getName() {
          188             return name;
          189         }
          190 
          191         public void setName(String name) {
          192             this.name = name;
          193         }
          194 
          195         public ProductDTO getProduct() {
          196             return product;
          197         }
          198 
          199         public void setProduct(ProductDTO product) {
          200             this.product = product;
          201         }
          202 
          203     }
          204 
          205 }
          206 

           

          posted on 2012-09-07 11:03 Nirvana reborn 閱讀(10439) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2012年9月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導航

          統計

          公告

          我好喜歡它,
          我的 QQ 66013804
          我想做技術流,可是我很懶,
          博客新地址:<a href="

          隨筆分類(19)

          文章檔案(1)

          博主鏈接

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 深圳市| 德格县| 宁海县| 长春市| 太和县| 阿荣旗| 凯里市| 桓台县| 娄底市| 星座| 嘉定区| 开封市| 桂平市| 门源| 新竹县| 迁西县| 葫芦岛市| 平江县| 苍溪县| 西林县| 南郑县| 那曲县| 万载县| 鸡东县| 鲁甸县| 四会市| 南乐县| 共和县| 宁乡县| 岱山县| 读书| 瑞昌市| 横山县| 盘山县| 万盛区| 环江| 定陶县| 慈利县| 榆中县| 民丰县| 双辽市|