使用 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。
- CycleAvoidingMappingContext -(这是避免循环(以及堆栈溢出的出现)所必需的)
@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);
}
- MapperUtils -(这是 MapStruct 的实用程序)
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;
}
- OrderDtoMapper - 它是我的基本界面,适用于 类 代
@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 会自动为您完成。它知道
我有一个实体在查询数据库期间得到 "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。
- CycleAvoidingMappingContext -(这是避免循环(以及堆栈溢出的出现)所必需的)
@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);
}
- MapperUtils -(这是 MapStruct 的实用程序)
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;
}
- OrderDtoMapper - 它是我的基本界面,适用于 类 代
@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 会自动为您完成。它知道