我正在为我的班级做一个项目。需要将DTO映射到实体,反之亦然。我的DTO没有Id字段,并且转换发生在控制器层。另外两个类正在扩展我的实体,因此@Superbuilder。
我的转换实体->DTO与ModelMapper配合良好
但是DTO->实体没有convertToEntity中的注释行我认为应该有效,但nope一直得到臭名昭著的">具有非私有无参数构造函数"。花了几个小时试图修复。决定采用更简单的解决方案,尽管确实想让ModelMapper正常工作。
如果你们中的任何人能帮我找到解决方案,我将不胜感激。提前感谢你们的时间和回应。
======我的DTO===
@Value
@Jacksonized
@Builder
@AllArgsConstructor
public class UserMetaData {
@NotNull @NotBlank @NotEmpty(message = "First name cannot be empty!")
@JsonProperty("firstName")
String firstName;
@NotNull @NotBlank @NotEmpty(message = "Last name cannot be empty!")
@JsonProperty("lastName")
String lastName;
@Max(value = 110, message = "Invalid age!") @Min(value = 16, message = "Must be older than 16!")
@JsonProperty("age")
int age;
@NotNull
@JsonProperty("privilege")
Privilege privilege;
//@NotNull
@JsonProperty("alias")
String alias;
//@Singular
@JsonProperty("groups")
Set<Group> groups;
}
=====我的实体=====
@Document(collection = "Users")
@SuperBuilder
@Data
@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
public class Member implements User {
@Id
protected final UUID id;
protected final String firstName;
protected final String lastName;
protected final int age;
@Builder.Default
protected final Privilege privilege = NONE;
protected String alias;
protected Set<Group> groups;
protected Set<Group> addGroup(Group group) {
this.groups.add(group);
return this.groups;
}
}
=====ModelMapper的Bean=====
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE);
return modelMapper;
}
=====转换器=====
private UserMetaData convertToDTO(Member member) {
return modelMapper.map(member, UserMetaData.UserMetaDataBuilder.class)
.build();
}
private Member convertToEntity(UserMetaData dto) {
// return modelMapper.map(dto, Member.MemberBuilder.class).id(UUID.randomUUID()).build();
return Member.builder()
.id(UUID.randomUUID())
.firstName(dto.getFirstName())
.lastName(dto.getLastName())
.age(dto.getAge())
.build();
}
您的DTO
类使用@Builder
,而Entity
类则使用@SuperBuilder
@Builder
和@SuperBuilder
之间存在差异。编译项目后查看target
文件:
@Builder
将创建一个名为DTOBuilder
的静态类,它有一个公共构造函数
public class DTO {
//...
public static class DTOBuilder {
public DTOBuilder() {
}
}
}
@SuperBuilder
将创建一个public abstract class EntityBuilder
和一个具有private constructor
的private implemented class EntityBuilderImpl
public class Entity {
//...
public abstract static class EntityBuilder<...> {
}
//...
private static final class EntityBuilderImpl extends EntityBuilder {
private EntityBuilderImpl() {
}
}
}
因此,ModelMapper
要求目标类应该是public class
和public contructor
。这就是为什么您不能映射到EntityBuilder
,但使用DTOBuilder
可以。
解决方案是,您应该直接映射到Entity,而不是映射到EntityBuilder
。注意,您的实体必须具有No Args Constructor
将@NoArgsConstructor
添加到实体中,并从DTO转换为实体类,而不是EntityBuilder
//...
@NoArgsConstructor
public class Member implements User {
//...
}
private Member convertToEntity(UserMetaData dto) {
return modelMapper.map(dto, Member.class);
}