Java MapStruct:Mapper 在映射单个元素之前清除目标集合
Java MapStruct: Mapper clears the target collection before it maps the individual elements
- 我想为集合中的元素创建一个自定义映射器。在我的例子中是一个 Set
问题:我的映射器没有对单个元素使用我的自定义映射方法。
这是我的代码:
RelatedCardObject 实体
此实体与卡片实体相关。 CardMapper 使用 RelatedCardObjectMapper 映射 Set
@Entity
@Table(name = "related_card_object")
public class RelatedCardObject {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "related_card_object_sequence")
@SequenceGenerator(name = "related_card_object_sequence", sequenceName = "related_card_object_seq")
private Long id;
@NotBlank
@NotNull
private String relatedCardObjectsScryfallId;
@NotBlank
@NotNull
private String object;
@NotBlank
@NotNull
private String name;
@NotBlank
@NotNull
private String typeLine;
@NotBlank
@NotNull
private String uri;
@NotNull
@ManyToMany(mappedBy = Card.ATTR_RELATEDCARDOBJECTS)
private Set<Card> cards;
// getters, setters & default constructor
}
RelatedCardObject DTO
@JsonIgnoreProperties(ignoreUnknown = true)
public class RelatedCardObjectDto implements Serializable {
@JsonIgnore
private Long id;
@JsonProperty("id")
private String relatedCardObjectsScryfallId;
@JsonProperty("object")
private String object;
@JsonProperty("name")
private String name;
@JsonProperty("type_line")
private String typeLine;
@JsonProperty("uri")
private String uri;
// getters, setters & default constructor
}
RelatedCardObjectMapper
@Mapper(componentModel = "spring")
public interface RelatedCardObjectMapper {
Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, @MappingTarget Set<RelatedCardObject> entities);
@Mapping(source = "dto.id", target = "entity.id", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, @MappingTarget RelatedCardObject entity);
}
生成了 RelatedCardObjectMapperImpl
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2020-11-01T11:58:42+0100",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 14 (Oracle Corporation)"
)
@Component
public class RelatedCardObjectMapperImpl implements RelatedCardObjectMapper {
@Override
public Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, Set<RelatedCardObject> entities) {
if ( dtos == null ) {
return null;
}
entities.clear();
for ( RelatedCardObjectDto relatedCardObjectDto : dtos ) {
entities.add( relatedCardObjectDtoToRelatedCardObject( relatedCardObjectDto ) ); // here I want it to call my method (`relatedCardObjectFromDto()`)
}
return entities;
}
@Override
public RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, RelatedCardObject entity) {
if ( dto == null ) {
return null;
}
if ( dto.getId() != null ) {
entity.setId( dto.getId() );
}
entity.setRelatedCardObjectsScryfallId( dto.getRelatedCardObjectsScryfallId() );
entity.setObject( dto.getObject() );
entity.setName( dto.getName() );
entity.setTypeLine( dto.getTypeLine() );
entity.setUri( dto.getUri() );
return entity;
}
protected RelatedCardObject relatedCardObjectDtoToRelatedCardObject(RelatedCardObjectDto relatedCardObjectDto) {
if ( relatedCardObjectDto == null ) {
return null;
}
RelatedCardObject relatedCardObject = new RelatedCardObject();
relatedCardObject.setId( relatedCardObjectDto.getId() );
relatedCardObject.setRelatedCardObjectsScryfallId( relatedCardObjectDto.getRelatedCardObjectsScryfallId() );
relatedCardObject.setObject( relatedCardObjectDto.getObject() );
relatedCardObject.setName( relatedCardObjectDto.getName() );
relatedCardObject.setTypeLine( relatedCardObjectDto.getTypeLine() );
relatedCardObject.setUri( relatedCardObjectDto.getUri() );
return relatedCardObject;
}
}
已从 CardMapper 正确调用生成的 MapperImpl 中的方法 updateRelatedCardObjectSetFromDto()
,并且存在正确的 DTO 和实体列表。
但是在映射单个元素之前,方法 updateRelatedCardObjectSetFromDto()
清除实体集合。
它不使用我对单个实体的自定义映射 (relatedCardObjectFromDto()
),而是使用生成的方法 (relatedCardObjectDtoToRelatedCardObject()
) 来映射单个实体。
- 如何让映射器使用我的自定义方法来映射个人
实体。
- 不应该在映射器之前清除集合
映射包含的实体,因为实体集合包含来自
包含实体数据库 ID 的数据库。
当您使用 Set
定义更新方法时,您实际上是在告诉 MapStruct 请用这个新集合中的元素更新我当前的集合。 MapStruct 无法知道集合中的哪个元素相同以及如何合并 2 个集合。
要实现您正在寻找的内容,您必须编写一些自定义代码。
@Mapper(componentModel = "spring")
public interface RelatedCardObjectMapper {
default Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, @MappingTarget Set<RelatedCardObject> entities) {
// Somehow find the matching object from dtos to update in entities and then invoke relatedCardObjectFromDto with it
}
@Mapping(source = "dto.id", target = "entity.id", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, @MappingTarget RelatedCardObject entity);
}
- 我想为集合中的元素创建一个自定义映射器。在我的例子中是一个 Set
问题:我的映射器没有对单个元素使用我的自定义映射方法。
这是我的代码:
RelatedCardObject 实体
此实体与卡片实体相关。 CardMapper 使用 RelatedCardObjectMapper 映射 Set
@Entity
@Table(name = "related_card_object")
public class RelatedCardObject {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "related_card_object_sequence")
@SequenceGenerator(name = "related_card_object_sequence", sequenceName = "related_card_object_seq")
private Long id;
@NotBlank
@NotNull
private String relatedCardObjectsScryfallId;
@NotBlank
@NotNull
private String object;
@NotBlank
@NotNull
private String name;
@NotBlank
@NotNull
private String typeLine;
@NotBlank
@NotNull
private String uri;
@NotNull
@ManyToMany(mappedBy = Card.ATTR_RELATEDCARDOBJECTS)
private Set<Card> cards;
// getters, setters & default constructor
}
RelatedCardObject DTO
@JsonIgnoreProperties(ignoreUnknown = true)
public class RelatedCardObjectDto implements Serializable {
@JsonIgnore
private Long id;
@JsonProperty("id")
private String relatedCardObjectsScryfallId;
@JsonProperty("object")
private String object;
@JsonProperty("name")
private String name;
@JsonProperty("type_line")
private String typeLine;
@JsonProperty("uri")
private String uri;
// getters, setters & default constructor
}
RelatedCardObjectMapper
@Mapper(componentModel = "spring")
public interface RelatedCardObjectMapper {
Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, @MappingTarget Set<RelatedCardObject> entities);
@Mapping(source = "dto.id", target = "entity.id", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, @MappingTarget RelatedCardObject entity);
}
生成了 RelatedCardObjectMapperImpl
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2020-11-01T11:58:42+0100",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 14 (Oracle Corporation)"
)
@Component
public class RelatedCardObjectMapperImpl implements RelatedCardObjectMapper {
@Override
public Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, Set<RelatedCardObject> entities) {
if ( dtos == null ) {
return null;
}
entities.clear();
for ( RelatedCardObjectDto relatedCardObjectDto : dtos ) {
entities.add( relatedCardObjectDtoToRelatedCardObject( relatedCardObjectDto ) ); // here I want it to call my method (`relatedCardObjectFromDto()`)
}
return entities;
}
@Override
public RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, RelatedCardObject entity) {
if ( dto == null ) {
return null;
}
if ( dto.getId() != null ) {
entity.setId( dto.getId() );
}
entity.setRelatedCardObjectsScryfallId( dto.getRelatedCardObjectsScryfallId() );
entity.setObject( dto.getObject() );
entity.setName( dto.getName() );
entity.setTypeLine( dto.getTypeLine() );
entity.setUri( dto.getUri() );
return entity;
}
protected RelatedCardObject relatedCardObjectDtoToRelatedCardObject(RelatedCardObjectDto relatedCardObjectDto) {
if ( relatedCardObjectDto == null ) {
return null;
}
RelatedCardObject relatedCardObject = new RelatedCardObject();
relatedCardObject.setId( relatedCardObjectDto.getId() );
relatedCardObject.setRelatedCardObjectsScryfallId( relatedCardObjectDto.getRelatedCardObjectsScryfallId() );
relatedCardObject.setObject( relatedCardObjectDto.getObject() );
relatedCardObject.setName( relatedCardObjectDto.getName() );
relatedCardObject.setTypeLine( relatedCardObjectDto.getTypeLine() );
relatedCardObject.setUri( relatedCardObjectDto.getUri() );
return relatedCardObject;
}
}
已从 CardMapper 正确调用生成的 MapperImpl 中的方法 updateRelatedCardObjectSetFromDto()
,并且存在正确的 DTO 和实体列表。
但是在映射单个元素之前,方法 updateRelatedCardObjectSetFromDto()
清除实体集合。
它不使用我对单个实体的自定义映射 (relatedCardObjectFromDto()
),而是使用生成的方法 (relatedCardObjectDtoToRelatedCardObject()
) 来映射单个实体。
- 如何让映射器使用我的自定义方法来映射个人 实体。
- 不应该在映射器之前清除集合 映射包含的实体,因为实体集合包含来自 包含实体数据库 ID 的数据库。
当您使用 Set
定义更新方法时,您实际上是在告诉 MapStruct 请用这个新集合中的元素更新我当前的集合。 MapStruct 无法知道集合中的哪个元素相同以及如何合并 2 个集合。
要实现您正在寻找的内容,您必须编写一些自定义代码。
@Mapper(componentModel = "spring")
public interface RelatedCardObjectMapper {
default Set<RelatedCardObject> updateRelatedCardObjectSetFromDto(Set<RelatedCardObjectDto> dtos, @MappingTarget Set<RelatedCardObject> entities) {
// Somehow find the matching object from dtos to update in entities and then invoke relatedCardObjectFromDto with it
}
@Mapping(source = "dto.id", target = "entity.id", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
RelatedCardObject relatedCardObjectFromDto(RelatedCardObjectDto dto, @MappingTarget RelatedCardObject entity);
}