我有一个基本的Spring引导应用程序,我正在尝试使用Mapstruct(版本1.3.0.Final)将实体列表映射到DTO列表。
来源:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.sql.Timestamp;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "source")
@Entity(name = "Source")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Source implements Serializable {
private static final long serialVersionUID = 964150155782995534L;
@Id
@JsonIgnore
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SourceSeq")
@SequenceGenerator(sequenceName = "source_id_seq", allocationSize = 1, name = "SourceSeq")
private long id;
@NotNull
@Size(min = 36, max = 36)
@Column(name = "uuid", nullable = false, length = 36)
private String uuid;
@Column(name = "user_id")
private Long userId;
@Column(name = "username")
private String username;
@Column(name = "user_org_id")
private Long userOrgId;
@Column(name = "user_org_name")
private String userOrgName;
@Column(name = "account_number")
private Integer accountNumber;
@Column(name = "account_name")
private String accountName;
@Column(name = "billing_delay")
private Integer billingDelay;
@Column(name = "default_billing_delay")
private Integer defaultBillingDelay;
@Column(name = "billing_enabled")
private Boolean billingEnabled = true;
@JsonIgnore
@CreationTimestamp
@Column(name = "created_date")
private Timestamp createdDate;
@JsonIgnore
@UpdateTimestamp
@Column(name = "updated_date")
private Timestamp updatedDate;
}
目标:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Target implements Serializable {
private static final long serialVersionUID = 8939532280496355293L;
@ApiModelProperty(hidden = true)
private String uuid;
@ApiModelProperty(value = "user ID", example = "123456", dataType = "int64", position = 1)
private Long userId;
@ApiModelProperty(value = "username", example = "myUser", position = 2)
private String username;
@ApiModelProperty(hidden = true)
private String firstName;
@ApiModelProperty(hidden = true)
private String lastName;
@ApiModelProperty(value = "user organization ID", example = "71836", dataType = "int64", position = 3)
private Long userOrgId;
@ApiModelProperty(value = "user organization name", example = "Org Inc", position = 4)
private String userOrgName;
@ApiModelProperty(value = "account number", example = "987654", position = 5)
private Integer accountNumber;
@ApiModelProperty(value = "account name", example = "My Mapping Acc", position = 6)
private String accountName;
@ApiModelProperty(value = "billing delay (in days)", example = "60", position = 7)
private Integer billingDelay;
@ApiModelProperty(value = "default billing delay (in days)", example = "30", position = 8)
private Integer defaultBillingDelay;
@ApiModelProperty(value = "is billing enabled?", example = "true", position = 9)
private Boolean billingEnabled = true;
@ApiModelProperty(hidden = true)
private Date createdDate;
}
映射器:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface MyMapper {
MyMapper MAPPER = Mappers.getMapper(MyMapper.class);
// Target toTarget(Source source);
// I have tried using this as well but my target mapped list only contains billingEnabled = true for every object in the response list. MapperImpl class also included below. Without toTarget method get a compilation error (also included below)
// Response:
/*[
{
"billingEnabled": true
},
{
"billingEnabled": true
},
{
"billingEnabled": true
}
]*/
List<Target> toTargets(List<Source> sources);
}
MapperImpl:
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2019-09-16T00:06:14-0700",
comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_202 (Oracle Corporation)"
)
public class MyMapperImpl implements MyMapper {
@Override
public Target toTarget(Source source) {
if ( source == null ) {
return null;
}
Target target = new Target();
return target;
}
@Override
public List<Target> toTargets(List<Source> sources) {
if ( sources == null ) {
return null;
}
List<Target> list = new ArrayList<Target>( sources.size() );
for ( Source source : sources ) {
list.add( toTarget( source ) );
}
return list;
}
}
错误:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) on project my-project: Compilation failure
[ERROR] /Users/user8812/workspace/my-project-/src/main/java/MyMapper.java:[17,23] Can't map Collection element "Source source" to "Target target". Consider to declare/implement a mapping method: "Target map(Source value)".
我正在寻找具有相同字段名的Target
列表,而没有另一个单独的toTarget
方法,而该方法已经在另一个具有较旧Mapstruct
版本的项目中为我工作。
答案 0 :(得分:0)
由于“目标”类型和“源”类型中的字段名称和类型相同,所以使用BeanUtils.copyProperties(source,target)会更有益,更容易吗?这非常简单,并允许陈述被忽略的字段。
答案 1 :(得分:0)
在编译过程中MapStruct引发的异常告诉您如何解决它:
无法将集合元素“源源”映射到“目标目标”。 考虑声明/实现映射方法:“目标映射(源值)”。
您甚至可以将此方法签名放置在与我们展示的相同的界面内。
修改
似乎该应用程序中MapStruct的默认全局配置已更改。尝试在界面内将此注释应用于您的“从源到目标”方法:
@BeanMapping(ignoreByDefault = false)
或者您可以使用@Mapping
注释显式映射它们的字段。
答案 2 :(得分:0)
我认为声明应该在MyMapper界面中具有注释。
@Mapping(source = "sources", target = "targets")
List<Target> toTargets(List<Source> sources);