Dozer是一種java bean映射工具,類似於apache的BeanUtils。主要作用是建立DTO與Entity之間的屬性關聯,區分對外接口實體與內部實體,避免兩者造成影響。
Dozer依賴於get與set方法,不能直接以public來訪問。
dozer支持雙向依賴,如A類中包含B對象、而B類中包含A對象。
對於兩個相互關聯的類,兩個屬性本質含義相同名字不同,則通過@Mapping()來進行轉換,而且只需要在一邊進行轉換即可。
dozer支持String和基礎類型的轉換。
dozer支持collection之間的轉換,或者數組與list轉換。
一、dozer可以由xml配置文件文件建立DTO與Entity之間管理。
案例:
1.book實體類:
public class Book {
private String name;
private String author;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Book() {
}
}
2.bookvo實體類:
public class BookVo {
private String namevo;
private String authorvo;
public String getNamevo() {
return namevo;
}
public void setNamevo(String namevo) {
this.namevo = namevo;
}
public String getAuthorvo() {
return authorvo;
}
public void setAuthorvo(String authorvo) {
this.authorvo = authorvo;
}
public BookVo() {
}
}
3.xml文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">
<mapping>
<class-a>test.Book</class-a>
<class-b>test.BookVo</class-b>
<field>
<a>name</a>
<b>namevo</b>
</field>
<field>
<a>author</a>
<b>authorvo</b>
</field>
</mapping>
</mappings>
4.測試類:
package test;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dozer.DozerBeanMapper;
/**
* 說明:
*
* @author lsr
* @version Aug 17, 2011
*/
public class DozerTest {
/**
* @param args
*/
public static void main(String[] args) {
testByXml();
}
public static void testByXml() {
Book book = new Book();
book.setAuthor("lsr");
book.setName("dozer demo");
DozerBeanMapper mapper = new DozerBeanMapper();
List<String> mappers = new ArrayList<String>();
mappers.add("bookMapper.xml");
mapper.setMappingFiles(mappers);
BookVo vo = new BookVo();
mapper.map(book, vo);
System.out.println("book's name:" + book.getName());
System.out.println("bookVo's name:" + vo.getNamevo());
}
}
二、dozer也可以由註解關聯。
案例:
1.product類:
public static class Product {
private String productName;
private Double price;
private List<Part> parts;
//DTO中沒有的屬性
private Double weight;
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public List<Part> getParts() {
return parts;
}
public void setParts(List<Part> parts) {
this.parts = parts;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
}
2.part類:
public static class Part {
//反向依賴Product
private Product product;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
3.productDTO:
public static class ProductDTO {
//定義到Product中的productName,只要在一邊定義,雙向轉換都可以使用.
@Mapping("productName")
private String name;
//類型爲String 而非 Double
private String price;
//類型爲Array而非List, PartDTO而非Part
private PartDTO[] parts;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public PartDTO[] getParts() {
return parts;
}
public void setParts(PartDTO[] parts) {
this.parts = parts;
}
}
4.partDTO:
public static class PartDTO {
//反向依賴ProductDTO
private ProductDTO product;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ProductDTO getProduct() {
return product;
}
public void setProduct(ProductDTO product) {
this.product = product;
}
}
5.測試類:
import static org.junit.Assert.*;
import java.util.List;
import org.dozer.Mapping;
import org.junit.Test;
import org.springside.modules.mapper.BeanMapper;
/**
* 演示Dozer如何只要屬性名相同,可以罔顧屬性類型是基礎類型<->String的差別,Array轉爲List,甚至完全另一種DTO的差別。
* 並且能完美解決循環依賴問題。
* 使用@Mapping能解決屬性名不匹配的情況.
*/
public class DozerDemo {
/**
* 從一個ProductDTO實例,創建出一個新的Product實例。
*/
@Test
public void map() {
ProductDTO productDTO = new ProductDTO();
productDTO.setName("car");
productDTO.setPrice("200");
PartDTO partDTO = new PartDTO();
partDTO.setName("door");
partDTO.setProduct(productDTO);
productDTO.setParts(new PartDTO[] { partDTO });
//ProductDTO->Product
Product product = BeanMapper.map(productDTO, Product.class);
assertEquals("car", product.getProductName());
//原來的字符串被Map成Double。
assertEquals(new Double(200), product.getPrice());
//原來的PartDTO同樣被Map成Part ,Array被Map成List
assertEquals("door", product.getParts().get(0).getName());
//Part中循環依賴的Product同樣被賦值。
assertEquals("car", product.getParts().get(0).getProduct().getProductName());
//再反向從Product->ProductDTO
ProductDTO productDTO2 = BeanMapper.map(product, ProductDTO.class);
assertEquals("car", productDTO2.getName());
assertEquals("200.0", productDTO2.getPrice());
assertEquals("door", productDTO2.getParts()[0].getName());
}
/**
* 演示將一個ProductDTO實例的內容,Copy到另一個已存在的Product實例.
*/
@Test
public void copy() {
ProductDTO productDTO = new ProductDTO();
productDTO.setName("car");
productDTO.setPrice("200");
PartDTO partDTO = new PartDTO();
partDTO.setName("door");
partDTO.setProduct(productDTO);
productDTO.setParts(new PartDTO[] { partDTO });
//已存在的Product實例
Product product = new Product();
product.setProductName("horse");
product.setWeight(new Double(20));
BeanMapper.copy(productDTO, product);
//原來的horse,被替換成car
assertEquals("car", product.getProductName());
//原來的20的屬性被覆蓋成200,同樣被從字符串被專爲Double。
assertEquals(new Double(200), product.getPrice());
//DTO中沒有的屬性值,在Product中被保留
assertEquals(new Double(20), product.getWeight());
//Part中循環依賴的Product同樣被賦值。
assertEquals("car", product.getParts().get(0).getProduct().getProductName());
}
}