简体   繁体   English

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

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

I have a entity object called TripEvent (persistence entity) .. see below the field i would like to draw attention to is createdby and the list List 我有一个称为TripEvent(持久性实体)的实体对象。请参见下面我要引起注意的字段createdby和列表List

@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;
.....
....

The TdfiFishGear class looks like the below snippet, again you can see a created by attribute. TdfiFishGear类看起来像下面的代码片段,再次您可以看到一个created by属性。

@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;

My DTO class Dep which is popluated via Json payload of a restful call looks like this... 我的DTO类Dep通过一个宁静的调用的Json有效负载填充,看起来像这样...

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;
  }

You can see if this DTO that there is no field called created by .. so on my mapping class you will see what i had to do, there are various calls to mappes which convert codes to ids etc etc 您可以查看是否该DTO没有由..创建的字段,因此在我的映射类上,您将看到我必须做的事情,有各种对mappe的调用,这些调用将代码转换为id等。

@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);

....
...

So there are fields outside the dto object that are required in the entity objects, the mapping is working perfectly aside from these fields. 因此,实体对象中需要dto对象外部的字段,因此除了这些字段之外,映射还可以正常工作。

So i am trying to figure out how i can populate a list of tdfiFishgears from depDTo.gea to include a createdby field that is not on the dto but is required on all instances in the list. 因此,我试图弄清楚如何从depDTo.gea中填充tdfiFishgears列表,以包括一个不在dto上但列表中所有实例都必需的createdby字段。 I have fudged this at the top level by passing them in as parameters of the method(interface).. i dont want to have to provide a custom mapper to loop through the list and instantiate and mapp the objkects manually as, the mapping is working 100% apart from this field(s .. i have more of them). 我已经通过将它们作为method(interface)的参数传入来在顶级进行了欺骗。.我不想提供自定义映射器来遍历列表并手动实例化和映射objkect,因为映射正在工作除了这个领域的100%(S ..我有更多)。

Any ideas...i should also mention that the DTO layer cannot be changed as it is from another team. 任何想法...我还应该提到DTO层不能更改,因为它是来自另一个团队的。

Here is an image of the error i am getting in the ide... error.png 这是我在思想中遇到的错误的图像... error.png

What you can do is to use @AfterMapping , @BeforeMapping together with the latest 1.2.0 (not yet final, at the time of the post Beta2 is out) @Context hooks so you can populate those fields. 您可以做的是将@AfterMapping@BeforeMapping与最新的1.2.0(在发布Beta2时尚未最终确定)一起使用@Context挂钩,以便可以填充这些字段。

It will look something like: 它看起来像:

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());
    }
}

If you don't want to have the @AfterMapping in your interface, you can also include it in the Context object. 如果您不想在界面中使用@AfterMapping ,也可以将其包含在Context对象中。

Like: 喜欢:

class ExtraFields {

    private String createdBy;

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM