java基礎之mapstruct


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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM