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)