使用 MapStruct 框架将实体对象转换为对象

Transform Entity-object into an Object with framework the MapStruct

我有一个实体在查询数据库期间得到 "userType"。

public class OrderEntityXml {

    @Id
    @SequenceGenerator(name = "jpa.Sequence.t.order", sequenceName = "T_ORDER_SEQ", allocationSize = 1)
    @GeneratedValue(generator = "jpa.Sequence.t.order", strategy = GenerationType.SEQUENCE)
    private Long id;

    private String customer;

    @Type(type = "Order")
    @Column(name = "order_xml")
    private Order order;

    public OrderEntityXml() {
    }

有一个从实体获取的容器。

杰克逊正在使用这个容器。

这个容器也在使用编组器和解组器

@XmlRootElement
@JacksonXmlRootElement(localName = "order")
public class Order implements Serializable {


    private String customer;

    @XmlElement(name = "orderItem")
    @JacksonXmlProperty(localName = "orderItem")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<OrderItem> orderItems = new ArrayList<>();

    public Order() {
    }

public class OrderItem {

    private String sku;

    private Double price;

    public OrderItem() {
    }

我已经设置了一个MapStruct。

@Component
public class CycleAvoidingMappingContext {

    private Map<Object, Object> knownInstances = new IdentityHashMap<Object, Object>();

    @BeforeMapping
    public <T> T getMappedInstance(Object source, @TargetType Class<T> targetType) {

        T t = (T) knownInstances.get(source);
        return t;
    }

    @BeforeMapping
    public void storeMappedInstance(Object source, @MappingTarget Object target) {
        knownInstances.put( source, target );
    }
}
public interface CommonMapper<D, E> {

    D toDto(E e, @Context CycleAvoidingMappingContext context);

    E toEntity(D d, @Context CycleAvoidingMappingContext context);

    Iterable<D> toListDto(Iterable<E> entityList);

    Iterable<E> toListEntity(Iterable<D> dtoList);

}


public static Order convertToDto(OrderEntityXml orderEntityXml){
        Order order = new Order();

        String customer = orderEntityXml.getCustomer();
        order.setCustomer(customer);

        Order xmlOrder = orderEntityXml.getOrder();
        List<OrderItem> orderItems = xmlOrder.getOrderItems();
        order.setOrderItems(orderItems);

        return order;
    }

    public static OrderEntityXml convertToEntity(Order order){

        OrderEntityXml orderEntityXml = new OrderEntityXml();
        String customer = order.getCustomer();
        orderEntityXml.setCustomer(customer);

        List<OrderItem> orderItems = order.getOrderItems();

        Order orderInEntity = new Order();

        orderInEntity.setOrderItems(orderItems);
        orderInEntity.setCustomer(customer);

        orderEntityXml.setOrder(orderInEntity);

        return orderEntityXml;
    }
@Mapper(componentModel = "spring")
public interface OrderDtoMapper extends CommonMapper<Order, OrderEntityXml> {

    @Override
    default Order toDto(OrderEntityXml orderEntityXml, CycleAvoidingMappingContext context) {

        return convertToDto(orderEntityXml);
    }

    @Override
    default OrderEntityXml toEntity(Order order, CycleAvoidingMappingContext context) {

        return convertToEntity(order);
    }


    @Override
    default Iterable<Order> toListDto(Iterable<OrderEntityXml> entityList) {

        Iterable<Order> collect = StreamSupport.stream(entityList.spliterator(), false)
            .map(MapperUtils::convertToDto)
            .collect(Collectors.toList());

        return collect;
    }
}

对于每种数据类型,您都必须制作自己的实用程序,这很麻烦。

我是否可以删除额外的代码并通过 MapStruct 接口对其进行配置? 我怀疑我把代码复杂化了。

谁能告诉你需要调整什么或可以将什么技术应用于 mapStruct 以统一代码

查看已发布的实体,我不明白您为什么需要使用 CycleAvoidingMappingContext。你的对象之间没有循环依赖。

为了避免您编写的手动代码,您可以使用 MapStruct @Mapping 注释来自定义某些字段需要如何映射。

所以在你的情况下它会是这样的:

@Mapper(componentModel = "spring")
public interface OrderDtoMapper extends CommonMapper<Order, OrderEntityXml> {

    @Override
    @Mapping(target = "orderItems", source = "order.orderItems")
    Order toDto(OrderEntityXml orderEntityXml, @Context CycleAvoidingMappingContext context);

    @Override
    @Mapping(target = "order", source = "order")
    OrderEntityXml toEntity(Order order, CycleAvoidingMappingContext context);

    Order cloneOrder(Order order);
}

您唯一需要的自定义如下:

  • 为了 toDto 告诉 MapStruct,当您从 OrderEntityXml 映射到 Order 时,您希望将 order.orderItems 映射到 orderItems
  • 为了 toEntity 告诉 MapStruct 当您从 Order 映射到 OrderEntityXml 时,您希望将方法 order 参数映射到 order 的 `OrderEntityXml
  • 另外我们添加 Order cloneOrder(Order) 以便 MapStruct 在 Order 之间映射时创建一个新对象,否则将使用相同的对象。

两种情况下的 customer 都会自动映射,因为它在两边都匹配。

无需为 Iterable 映射提供自定义方法,因为 MapStruct 会自动为您完成。它知道