PO,Persistent Object,持久对象,对应数据库表的对象模型。
DTO,Data Transfer Object,传输对象,前端发给后端的请求对象。
VO,View Object,视图对象,后端返回给前端的对象。
讲解一下最新的对象拷贝工具:mapstruct
经常看到的问题就是entity---->vo这种关系的赋值,也就是两个对象之间进行相互赋值的关系。
如果说两个对象的属性是相同的还好,如果是不同的,那么可能就非常麻烦的来进行转换了。
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.2.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </dependency>
然后在插件位置上进行配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <annotationProcessorPaths> <!-- 必须要加, 否则生成不了 MapperImpl 实现类 --> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </path> <!-- 如果是 0.1.0 有可能出现生成了maptruct的实现类, 但该类只创建了对象, 没有进行赋值 --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.guang.mapstruct.MapstructApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
然后编写两个类测试:
@Data @NoArgsConstructor @AllArgsConstructor public class Product { private Integer id; private String name; private Double price; }
@Data @NoArgsConstructor @AllArgsConstructor public class ProductVO { private Integer id; private String name; private Double price; }
然后编写一个接口:
import com.guang.mapstruct.pojo.Product; import com.guang.mapstruct.pojo.ProductVO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; @Mapper public interface ProductMapper { ProductMapper mapper = Mappers.getMapper(ProductMapper.class); /** * 将product转换成productvo * * @param product * @return */ @Mappings({ @Mapping(source = "id", target = "id"), @Mapping(source = "name", target = "name"), @Mapping(source = "price", target = "price") }) ProductVO product2VO(Product product); }
编写测试代码:
@Test void contextLoads() { Product product = new Product(1, "apple", 3.00); ProductVO productVO = ProductMapper.mapper.product2VO(product); System.out.println(productVO); }
控制台输出:
ProductVO(id=1, name=apple, price=3.0)
其实应用并非都是如此,还可以来给不同属性名字的类来进行赋值。
修改实体类属性之后:
@Data @NoArgsConstructor @AllArgsConstructor public class Product { private Integer id; private String name; private Double price; }
@Data @NoArgsConstructor @AllArgsConstructor public class ProductVO { private Integer pid; private String pname; private Double price; }
@Mapper public interface ProductMapper { ProductMapper mapper = Mappers.getMapper(ProductMapper.class); /** * 将product转换成productvo * * @param product * @return */ @Mappings({ @Mapping(source = "id", target = "pid"), @Mapping(source = "name", target = "pname"), @Mapping(source = "price", target = "price") }) ProductVO product2VO(Product product); }
结果发现控制台还是一样的。
那么我们查看一下对应的实现类:
@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2021-11-01T01:31:14+0800", comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_301 (Oracle Corporation)" ) public class ProductMapperImpl implements ProductMapper { @Override public ProductVO product2VO(Product product) { if ( product == null ) { return null; } ProductVO productVO = new ProductVO(); productVO.setPid( product.getId() ); productVO.setPname( product.getName() ); productVO.setPrice( product.getPrice() ); return productVO; } }
从这里可以看出来也是非常的简单的操作。
再来试一个:
@Mapper public interface ProductMapper { ProductMapper mapper = Mappers.getMapper(ProductMapper.class); /** * 将product转换成productvo * * @param product * @return */ @Mappings({ @Mapping(source = "id", target = "pid"), @Mapping(source = "name", target = "pname"), @Mapping(source = "price", target = "price") }) ProductVO product2VO(Product product); /** * 集合转换成集合操作 * @param productList * @return */ List<ProductVO> list2VO(List<Product> productList); }
测试方法:
@Test public void testList2List(){ List<Product> productList = new ArrayList<>(); for (int i = 0; i < 6; i++) { productList.add(new Product(i,"apple"+i,3.00)); } List<ProductVO> productVOS = ProductMapper.mapper.list2VO(productList); for (ProductVO productVO : productVOS) { productVO.setPid(7); System.out.println(productVO); } System.out.println("-----------------"); productList.forEach(System.out::println); }
控制台打印:
ProductVO(pid=7, pname=apple0, price=3.0) ProductVO(pid=7, pname=apple1, price=3.0) ProductVO(pid=7, pname=apple2, price=3.0) ProductVO(pid=7, pname=apple3, price=3.0) ProductVO(pid=7, pname=apple4, price=3.0) ProductVO(pid=7, pname=apple5, price=3.0) ----------------- Product(id=0, name=apple0, price=3.0) Product(id=1, name=apple1, price=3.0) Product(id=2, name=apple2, price=3.0) Product(id=3, name=apple3, price=3.0) Product(id=4, name=apple4, price=3.0) Product(id=5, name=apple5, price=3.0)
那么看一下具体的实现类:
@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2021-11-01T01:46:02+0800", comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_301 (Oracle Corporation)" ) public class ProductMapperImpl implements ProductMapper { @Override public ProductVO product2VO(Product product) { if ( product == null ) { return null; } ProductVO productVO = new ProductVO(); productVO.setPid( product.getId() ); productVO.setPname( product.getName() ); productVO.setPrice( product.getPrice() ); return productVO; } @Override public List<ProductVO> list2VO(List<Product> productList) { if ( productList == null ) { return null; } // 可以看到这里在循环的调用上面的方法来进行实现 List<ProductVO> list = new ArrayList<ProductVO>( productList.size() ); for ( Product product : productList ) { list.add( product2VO( product ) ); } return list; } }
除此之外,再见一个比较秀的操作:
将两个类合并成一个类:
@Data @NoArgsConstructor @AllArgsConstructor public class Category { private String type; } @Data @NoArgsConstructor @AllArgsConstructor public class Product { private Integer id; private String name; private Double price; } @Data @NoArgsConstructor @AllArgsConstructor public class OrderVO { private String orderType; private String name; }
这里是想将Category中的type和Product中的name赋值给OrderVO中的属性中来
那么在Mapper中继续来进行配置
@Mapper public interface ProductMapper { ProductMapper mapper = Mappers.getMapper(ProductMapper.class); /** * 将product转换成productvo * * @param product * @return */ @Mappings({ @Mapping(source = "id", target = "pid"), @Mapping(source = "name", target = "pname"), @Mapping(source = "price", target = "price") }) ProductVO product2VO(Product product); /** * 集合转换成集合操作 * @param productList * @return */ List<ProductVO> list2VO(List<Product> productList); /** * 将Category中的category和Product中的product属性赋值给OrderVO * @param category * @param product * @return */ @Mappings({ @Mapping(source = "category.type",target = "orderType"), @Mapping(source = "product.name",target = "name") }) OrderVO createVO(Category category,Product product); }
那么测试一下:
@Test public void testCreateOrderVO(){ Category category = new Category("电子产品"); Product product= new Product(1,"lianxiang",2.00); OrderVO orderVO = ProductMapper.mapper.createVO(category, product); System.out.println(orderVO); }
控制台输出打印:
OrderVO(orderType=电子产品, name=lianxiang)
看一下对应的实现类:
@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2021-11-01T02:00:52+0800", comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_301 (Oracle Corporation)" ) public class ProductMapperImpl implements ProductMapper { @Override public ProductVO product2VO(Product product) { if ( product == null ) { return null; } ProductVO productVO = new ProductVO(); productVO.setPid( product.getId() ); productVO.setPname( product.getName() ); productVO.setPrice( product.getPrice() ); return productVO; } @Override public List<ProductVO> list2VO(List<Product> productList) { if ( productList == null ) { return null; } List<ProductVO> list = new ArrayList<ProductVO>( productList.size() ); for ( Product product : productList ) { list.add( product2VO( product ) ); } return list; } @Override public OrderVO createVO(Category category, Product product) { if ( category == null && product == null ) { return null; } OrderVO orderVO = new OrderVO(); if ( category != null ) { orderVO.setOrderType( category.getType() ); } if ( product != null ) { orderVO.setName( product.getName() ); } return orderVO; } }
最后一个,转换的方法:
@Data @NoArgsConstructor @AllArgsConstructor public class Goods { private Integer goodId; private String goodName; private Double goodPrice; /** * 0代表下架 * 1代表正常 */ private Integer status; }
@Data @NoArgsConstructor @AllArgsConstructor public class ProductVO { private Integer pid; private String pname; private Double price; private Boolean status; }
mapper接口编写:
@Mapper public interface GoodsMapper { GoodsMapper mapper = Mappers.getMapper(GoodsMapper.class); @Mappings({ @Mapping(source = "goodId", target = "pid"), @Mapping(source = "goodName", target = "pname"), @Mapping(source = "goodPrice", target = "price"), // 但是这里需要做一个转换操作 @Mapping(source = "status", target = "status",qualifiedByName = "transfer") }) ProductVO goods2VO(Goods goods); @Named("transfer") default Boolean transfer(Integer status) { return status == 1; } }
编写对应的测试类:
@Test public void testTransfer(){ Goods goods = new Goods(1,"APPLE",2.13,0); ProductVO productVO = GoodsMapper.mapper.goods2VO(goods); System.out.println(productVO); }
对应的输出:
ProductVO(pid=1, pname=APPLE, price=2.13, status=false)