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);
}
}
我有一个名为 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);
}
}