- Published on
Java-Mapstruct 实践
1. 基本映射
1.1 简单字段映射
@Mapper
public interface UserMapper {
@Mapping(source = "firstName", target = "name")
@Mapping(source = "age", target = "userAge")
UserDto userToUserDto(User user);
}
1.2 多个源对象映射到一个目标对象
@Mapper
public interface OrderMapper {
@Mapping(source = "order.id", target = "orderId")
@Mapping(source = "customer.name", target = "customerName")
OrderDto orderAndCustomerToOrderDto(Order order, Customer customer);
}
2. 集合映射
2.1 列表映射
@Mapper
public interface ProductMapper {
List<ProductDto> productsToProductDtos(List<Product> products);
}
🔊🔊 当进行列表映射,且源实体和目标实体的属性名称不同时,
MapStruct
提供了几种处理方法。以下是详细说明:
首先,让我们定义源实体和目标实体:
public class Product {
private Long id;
private String productName;
private BigDecimal cost;
// getters and setters
}
public class ProductDto {
private Long productId;
private String name;
private BigDecimal price;
// getters and setters
}
然后,我们可以这样定义映射器:
@Mapper
public interface ProductMapper {
@Mapping(source = "id", target = "productId")
@Mapping(source = "productName", target = "name")
@Mapping(source = "cost", target = "price")
ProductDto productToProductDto(Product product);
List<ProductDto> productsToProductDtos(List<Product> products);
}
在这个例子中(🧑💻🧑💻):
productToProductDto
方法定义了单个对象的映射规则。productsToProductDtos
方法用于列表映射。MapStruct 会自动使用productToProductDto
方法的规则来映射列表中的每个元素。
自定义映射方法
@Mapper
public abstract class ProductMapper {
@Mapping(source = "id", target = "productId")
@Mapping(source = "productName", target = "name")
@Mapping(source = "cost", target = "price")
abstract ProductDto productToProductDto(Product product);
public List<ProductDto> productsToProductDtos(List<Product> products) {
if (products == null) {
return null;
}
List<ProductDto> list = new ArrayList<>(products.size());
for (Product product : products) {
list.add(productToProductDto(product));
}
return list;
}
// 可以添加一些自定义的辅助方法
protected BigDecimal adjustPrice(BigDecimal cost) {
// 例如,增加 10% 的利润
return cost.multiply(new BigDecimal("1.1"));
}
}
使用 @IterableMapping
如果需要对列表映射应用额外的配置,可以使用 @IterableMapping
注解:
@Mapper
public interface ProductMapper {
@Mapping(source = "id", target = "productId")
@Mapping(source = "productName", target = "name")
@Mapping(source = "cost", target = "price")
ProductDto productToProductDto(Product product);
@IterableMapping(elementTargetType = ProductDto.class)
List<ProductDto> productsToProductDtos(List<Product> products);
}
这在处理泛型或需要明确指定目标类型时特别有用。
处理不同类型的集合,MapStruct 也支持在不同类型的集合之间进行映射:
@Mapper
public interface ProductMapper {
@Mapping(source = "id", target = "productId")
@Mapping(source = "productName", target = "name")
@Mapping(source = "cost", target = "price")
ProductDto productToProductDto(Product product);
List<ProductDto> productsToProductDtos(Collection<Product> products);
Set<ProductDto> productsToProductDtoSet(List<Product> products);
}
带有条件的列表映射,如果需要在映射过程中应用一些条件,可以结合使用
@Mapping
和自定义方法:
@Mapper
public abstract class ProductMapper {
@Mapping(source = "id", target = "productId")
@Mapping(source = "productName", target = "name")
@Mapping(source = "cost", target = "price")
@Mapping(target = "onSale", expression = "java(isOnSale(product))")
abstract ProductDto productToProductDto(Product product);
abstract List<ProductDto> productsToProductDtos(List<Product> products);
protected boolean isOnSale(Product product) {
// 实现判断商品是否在销售的逻辑
return product.getCost().compareTo(new BigDecimal("100")) < 0;
}
}
2.2 Map映射
@Mapper
public interface InventoryMapper {
Map<String, Integer> inventoryToStockMap(Map<Product, Integer> inventory);
}
3. 嵌套对象映射
@Mapper
public interface AddressMapper {
@Mapping(source = "user.address.street", target = "streetName")
@Mapping(source = "user.address.city", target = "cityName")
AddressDto userToAddressDto(User user);
}
4. 默认值和常量
@Mapper
public interface EmployeeMapper {
@Mapping(target = "employeeId", source = "entity.id")
@Mapping(target = "employeeName", source = "entity.name")
@Mapping(target = "employeeStartDt", source = "entity.startDate", dateFormat = "dd-MM-yyyy HH:mm:ss")
@Mapping(target = "status", constant = "ACTIVE")
EmployeeDto employeeToEmployeeDTO(Employee entity);
}
5. 自定义方法
@Mapper
public abstract class UserMapper {
@Mapping(target = "fullName", expression = "java(fullName(user))")
public abstract UserDto userToUserDto(User user);
protected String fullName(User user) {
return user.getFirstName() + " " + user.getLastName();
}
}
6. 继承映射
@Mapper
public interface VehicleMapper {
VehicleDto vehicleToVehicleDto(Vehicle vehicle);
@InheritConfiguration
CarDto carToCarDto(Car car);
}
7. 更新已存在的实例
@Mapper
public interface CustomerMapper {
void updateCustomerFromDto(CustomerDto dto, @MappingTarget Customer customer);
}
8. 忽略某些字段
@Mapper
public interface ProductMapper {
@Mapping(target = "id", ignore = true)
@Mapping(target = "createdAt", ignore = true)
Product dtoToProduct(ProductDto dto);
}
9. 条件映射
@Mapper
public interface OrderMapper {
@Mapping(target = "customerName", source = "customer.name")
@Mapping(target = "priorityOrder", source = "priority",
condition = "java(priority > 5)")
OrderDto orderToOrderDto(Order order);
}
参考链接
- MapStruct 官方文档
- MapStruct GitHub