Mapstruct 映射查询:将属性从 dto 映射到实体而不是 dto 中的属性

Mapstruct mapping query :mapping an attribute from dto to entity but not an attibute on dto

我有一个名为 TripEvent 的实体对象(持久性实体).. 请参阅下面我想提请注意的字段是 createdby 和列表 列表

@Entity
@Table(name = "TRIPEVENT")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@tripeventId")
public class Tripevent implements Serializable {

...
...

 @Id
 @SequenceGenerator(name = OracleConstants.TRIPEVENT_TRIPEVENTID_GENERATOR, sequenceName = OracleConstants.TRANSACTIONSEQUENCE_NAME, allocationSize = OracleConstants.TRANSACTIONSEQUENCE_ALLOCATION_SIZE)
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = OracleConstants.TRIPEVENT_TRIPEVENTID_GENERATOR)
 @Column(unique = true, nullable = false, precision = 10)
 private long tripeventid;


 @Column(precision = 10)
 private Long activitytypeid;

 @Column(nullable = false, length = 1)
 private String alertind;

 @Column(nullable = false, length = 1)
 private String completedind;

 @Column(nullable = false)
 private Timestamp createdate;

 @Column(nullable = false, length = 20)
 private String createdby;
....
....
 @OneToMany(mappedBy = "tripevent", cascade = CascadeType.PERSIST)
 @JsonManagedReference(value = "tripevent-fishgear")
     private List<TdfiFishgear> tdfiFishgears;
.....
....

TdfiFishGear class 看起来像下面的代码片段,您可以再次看到创建者属性。

@Entity
@Table(name = "TDFI_FISHGEAR")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@fishgearId")
public class TdfiFishgear implements Serializable {
 private static final long serialVersionUID = 1L;


 @Id
 @SequenceGenerator(name = OracleConstants.TDFI_FISHGEAR_TDFIFISHGEARID_GENERATOR, sequenceName = OracleConstants.TRANSACTIONSEQUENCE_NAME, allocationSize = OracleConstants.TRANSACTIONSEQUENCE_ALLOCATION_SIZE)
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = OracleConstants.TDFI_FISHGEAR_TDFIFISHGEARID_GENERATOR)
 @Column(name = "TDFI_FISHGEARID", unique = true, nullable = false, precision = 10)
 private long tdfiFishgearid;


 @Column(precision = 8)
 private Long avghookcount;


 @Column(precision = 15, scale = 3)
 private BigDecimal avgnetheight;


 @Column(precision = 10)
 private Long avgnetheighuomid;


 @Column(precision = 15, scale = 3)
 private BigDecimal avgnetlength;


 @Column(precision = 10)
 private Long avgnetlengthuomid;


 @Column(nullable = false)
 private Timestamp createdate;


 @Column(nullable = false, length = 20)
 private String createdby;


 @Column(precision = 6, scale = 1)
 private BigDecimal fishingdepth;


 @Column(nullable = false, precision = 10)
 private Long geartypeid;


 @Column(nullable = false, length = 1)
 private String inactiveind;


 private Timestamp lastchangedate;

我的 DTO class 通过 restful 调用的 Json 负载填充的 Dep 看起来像这样...

public class Dep   {

  public Dep(){  
  }

  @NotEmpty(message = "seqNo: is a required field")
  @JsonProperty("seqNo")
  private String seqNo = null;


  @NotNull(message = "depTStamp: is a required field")
  @JsonProperty("depTStamp")
  private ZonedDateTime depTStamp = null;


  @NotEmpty(message = "port: is a required field")
  @JsonProperty("port")
  private String port = null;


  @JsonProperty("nonEUPort")
  private String nonEUPort = null;


  @NotEmpty(message = "activity: is a required field")
  @JsonProperty("activity")
  private String activity = null;


  @JsonProperty("comments")
  private String comments = null;


  @JsonProperty("spe")
  @Valid
  private List<DepSpe> spe = new ArrayList<DepSpe>();


  @JsonProperty("gea")
  @Valid
  private List<NonFarGea> gea = new ArrayList<NonFarGea>();


  public Dep seqNo(String seqNo) {
    this.seqNo = seqNo;
    return this;
  }

你可以看到这个 DTO 是否没有由 ..等等等等

@Mapper(componentModel="spring",
uses = {
 ZonedDateTimeStampMapper.class, 
 ConfigMapperFromCode.class,
 RasDepMapper.class
 },
 unmappedTargetPolicy = ReportingPolicy.IGNORE
)


public interface DepToTripEventMapperApi {


 /*root mapper from a dep dto to a entity trip event*/

 @Mappings(
  {
    @Mapping(target = "createdby", source = "regUserId"),
    @Mapping(target = "createdate",expression = "java(java.sql.Timestamp.valueOf(java.time.LocalDateTime.now()))"),
    @Mapping(target = "inactiveind", constant = "N"),
    @Mapping(target = "eventtypeid", qualifiedByName={"ConfigMapperFromCode", "returnDepEventId"}),
    @Mapping(target = "activitytypeid", qualifiedByName={"ConfigMapperFromCode", "activityIdFromCode"}, source="depDto.activity"),
    @Mapping(target = "marineportid", qualifiedByName={"ConfigMapperFromCode", "portIdFromCode"}, source = "depDto.port"),
    @Mapping(target = "alertind", constant = "N"),
    @Mapping(target = "eventnote", source = "depDto.nonEUPort"),
    @Mapping(target = "ersseqno", source = "depDto.seqNo"),
    @Mapping(target = "skippercomment", source = "depDto.comments"),
    @Mapping(target = "tdfiErsmessageid", source = "messageId"),
    @Mapping(target = "startdate", source = "depDto.depTStamp"),
    @Mapping(target = "completedind", constant = "N"),
    @Mapping(target = "vessel", source = "vessell"),
    @Mapping(target = "triplogs", source = "tripLogs"),
    @Mapping(target = "lastchangedate", ignore = true),
    @Mapping(target = "lastchangedby", ignore = true),
    @Mapping(target = "tdfiCatchmovements", ignore = true),
    @Mapping(target = "tdfiFishgears", source="depDto.gea"),
    ..
  }
 )
 Tripevent DepDtoToTripEvent(Dep depDto, String regUserId, Long messageId, Vessel vessell, List<Triplog>tripLogs);



 // mapper from nonnfargea to fishing gear
 @Mappings(
 {
 @Mapping(target = "meshdimension", source = "gea.gearDims"),
 @Mapping(target = "geartypeid", qualifiedByName={"ConfigMapperFromCode", "gearIdFromCode"},  source = "gea.gearType"),
 @Mapping(target = "avgnetheight", source = "gea.avNetHeight"),
 @Mapping(target = "avgnetlength", source = "gea.avNetLength"),
 @Mapping(target = "meshsize", source = "gea.meshSize"),
 @Mapping(target = "avghookcount", source = "gea.avHooks"),
 @Mapping(target = "totnetquantity", source = "gea.noNets"),
 @Mapping(target = "tothookscount", source = "gea.totHooks"),
 @Mapping(target = "totnetlength", source = "gea.totLen"), 
 @Mapping(target = "trawltypeid", qualifiedByName={"ConfigMapperFromCode", "speciesIdFromCode"},  source = "gea.trawlType")
 }
 )
 TdfiFishgear geaToFishGear(NonFarGea gea);

....
...

所以在实体对象中有 ide dto 对象之外的字段,映射与这些字段中的 ide 一样完美。

所以我想弄清楚如何从 depDTo.gea 填充 tdfiFishgears 列表以包含一个不在 dto 上但列表中所有实例都需要的 createdby 字段。我通过将它们作为方法(接口)的参数传递来在顶层捏造了这个。我不想提供 ide 自定义映射器来遍历列表并手动实例化和映射对象作为,除了这个字段之外,映射工作 100%(s .. 我有更多)。

任何 ideas...我还应该提到 DTO 层不能更改,因为它来自另一个团队。

这是我在 ide...error.png

中遇到的错误的图像

你可以做的是将@AfterMapping@BeforeMapping和最新的1.2.0一起使用(还不是最终版,在post Beta2出来的时候)@Context 挂钩,以便您可以填充这些字段。

它看起来像:

class ExtraFields {

    private String createdBy;
    //Getters omitted
}

public interface DepToTripEventMapperApi {

    //Your mappings
    Tripevent DepDtoToTripEvent(Dep depDto, String regUserId, Long messageId, Vessel vessell, List<Triplog>tripLogs, @Context ExtraFields extra);

    //Your mappings
    TdfiFishgear geaToFishGear(NonFarGea gea, @Context ExtraFields extra);

    @AfterMapping
    default void afterMapping(@MappingTarget TdfiFishgear fea, @Context ExtraFields extra) {
        fea.setCreatedBy(extra.getCreatedBy());
    }
}

如果您不想在界面中包含 @AfterMapping,您也可以将其包含在 Context 对象中。

喜欢:

class ExtraFields {

    private String createdBy;

    public ExtraField(String createdBy) {
        this.createdBy = createdBy;
    }

    @AfterMapping
    public void afterFishGear(@MappingTarget fishGear) {
        fishGear.setCreatedBy(createdBy);
    }
}