我还在学习,所以不要严格评判)
两个问题:1)映射中的错误--没有将列表对象设置为镜像对象(在一个方向上列表是空的,在另一个方向上列表长度超出界限0)2)对象层次结构映射的优化
@MappedSuperclass
@Data
@NoArgsConstructor
public abstract class BusinessEntity {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "id", updatable = false, nullable = false)
private UUID id;
@Column(updatable = false)
@CreationTimestamp
private LocalDateTime createdOn;
@UpdateTimestamp
private LocalDateTime modifiedOn;
private LocalDateTime deletedOn;
@NotNull
private boolean SystemProtectedStatus = false;
@NotNull
private boolean SuspendedStatus = false;
@NotNull
private boolean blockedStatus = false;
@NotNull
private boolean deletedStatus = false;
private LocalDateTime activeFrom;
private LocalDateTime activeUntil;
}
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SystemRights extends BusinessEntity {
@NotNull
private String name;
private String description;
public SystemRights(@NotNull String name) {
super();
this.name = name;
}
}
@EqualsAndHashCode(callSuper = true)
@Entity
@Data
@NoArgsConstructor
public class UserRole extends BusinessEntity{
@NotNull
private String name;
private String description;
@ManyToMany
@JoinTable(
name = "rights_in_roles"
, joinColumns = @JoinColumn(name = "right_id")
, inverseJoinColumns = @JoinColumn (name = "role_id")
)
public List<SystemRights> systemRights;
public UserRole(@NotNull String name) {
this.name = name;
}
public List<SystemRights> getSystemRights() {
if (systemRights == null)
systemRights = new ArrayList<>();
return systemRights;
}
public void addSystemRights(SystemRights newSystemRights) {
if (newSystemRights == null)
return;
if (this.systemRights == null)
this.systemRights = new ArrayList<>();
this.systemRights.add(newSystemRights);
}
public void removeSystemRights(SystemRights oldSystemRights) {
if (oldSystemRights == null)
return;
if (this.systemRights != null)
this.systemRights.remove(oldSystemRights);
}
public void removeAllSystemRights() {
if (systemRights != null)
systemRights.clear();
}
}
我想将其映射到DTO中,如下所示:(实际上是一对一)
@Data
public abstract class Dto {
private String id;
private String activeFrom;
private String activeUntil;
private boolean SystemProtectedStatus;
private boolean SuspendedStatus;
private boolean blockedStatus;
private boolean deletedStatus;
private String createdOn;
// private User createdBy;
private String modifiedOn;
// private User modifiedBy;
private String deletedOn;
// private User deletedBy;
}
@Data
public class SystemRightsDto extends Dto{
@NotNull
private String name;
private String description;
}
@Data
public class UserRoleDto extends Dto {
@NotNull
private String name;
private String description;
@NotNull
public List<SystemRightsDto> systemRightsDto;
}
为了做到这一点,我把这些映射器堆在下面。-这是第一个问题:-在MapStruct中,如何正确地从根实体BusinessEntity继承映射,它是系统中所有记帐对象的祖先,而不像我在培训中遇到的那样,复制粘贴到每个子对象?
@Mapper
public interface UserRoleMapper {
@Mapping(target = "id",
expression = "java(getStringFromId(entity.getId()))")
@Mapping(target = "activeFrom",
expression = "java(getStringfromLDT(entity.getActiveFrom()))")
@Mapping(target = "activeUntil",
expression = "java(getStringfromLDT(entity.getActiveUntil()))")
@Mapping(target = "createdOn",
expression = "java(getStringfromLDT(entity.getCreatedOn()))")
@Mapping(target = "modifiedOn",
expression = "java(getStringfromLDT(entity.getModifiedOn()))")
@Mapping(target = "deletedOn",
expression = "java(getStringfromLDT(entity.getDeletedOn()))")
UserRoleDto getDtoFromEntity(UserRole entity);
@Mapping(target = "id",
expression = "java(getIdFromString(dto.getId()))")
@Mapping(target = "activeFrom",
expression = "java(getLDTfromString(dto.getActiveFrom()))")
@Mapping(target = "activeUntil",
expression = "java(getLDTfromString(dto.getActiveUntil()))")
@Mapping(target = "createdOn",
expression = "java(getLDTfromString(dto.getCreatedOn()))")
@Mapping(target = "modifiedOn",
expression = "java(getLDTfromString(dto.getModifiedOn()))")
@Mapping(target = "deletedOn",
expression = "java(getLDTfromString(dto.getDeletedOn()))")
UserRole getEntityFromDto(UserRoleDto dto);
List<SystemRights> SystemRightsDtoToEnt (List<SystemRightsDto> dto);
List<SystemRightsDto> SystemRightsEntToDto (List<SystemRights> entity);
default LocalDateTime getLDTfromString(String string) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
if (!isNull(string)) {
return LocalDateTime.parse(string, formatter);
} else {
return null;
}
}
default String getStringfromLDT(LocalDateTime ldt) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
if (!isNull(ldt)) {
return ldt.toString();
} else {
return null;
}
}
default String getStringFromId(UUID id) {
if (!isNull(id)) {
return id.toString();
} else {
return null;
}
}
default UUID getIdFromString(String id) {
if (!isNull(id)) {
return UUID.fromString(id);
} else {
return null;
}
}
}
@Mapper
public interface SystemRightsMapper {
@Mapping(target = "id",
expression = "java(getStringFromId(entity.getId()))")
@Mapping(target = "activeFrom",
expression = "java(getStringfromLDT(entity.getActiveFrom()))")
@Mapping(target = "activeUntil",
expression = "java(getStringfromLDT(entity.getActiveUntil()))")
@Mapping(target = "createdOn",
expression = "java(getStringfromLDT(entity.getCreatedOn()))")
@Mapping(target = "modifiedOn",
expression = "java(getStringfromLDT(entity.getModifiedOn()))")
@Mapping(target = "deletedOn",
expression = "java(getStringfromLDT(entity.getDeletedOn()))")
SystemRightsDto getDtoFromEntity(SystemRights entity);
@Mapping(target = "id",
expression = "java(getIdFromString(dto.getId()))")
@Mapping(target = "activeFrom",
expression = "java(getLDTfromString(dto.getActiveFrom()))")
@Mapping(target = "activeUntil",
expression = "java(getLDTfromString(dto.getActiveUntil()))")
@Mapping(target = "createdOn",
expression = "java(getLDTfromString(dto.getCreatedOn()))")
@Mapping(target = "modifiedOn",
expression = "java(getLDTfromString(dto.getModifiedOn()))")
@Mapping(target = "deletedOn",
expression = "java(getLDTfromString(dto.getDeletedOn()))")
SystemRights getEntityFromDto(SystemRightsDto dto);
List<SystemRights> SystemRightsDtoToEnt (List<SystemRightsDto> dto);
List<SystemRightsDto> SystemRightsEntToDto (List<SystemRights> entity);
default LocalDateTime getLDTfromString(String string) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
if (!isNull(string)) {
return LocalDateTime.parse(string, formatter);
} else {
return null;
}
}
default String getStringfromLDT(LocalDateTime ldt) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
if (!isNull(ldt)) {
return ldt.toString();
} else {
return null;
}
}
default String getStringFromId(UUID id) {
if (!isNull(id)) {
return id.toString();
} else {
return null;
}
}
default UUID getIdFromString(String id) {
if (!isNull(id)) {
return UUID.fromString(id);
} else {
return null;
}
}
}
SystemRights传输测试以两种方式工作,但UserRole测试失败。测试本身是这样的:
public class UserRoleMapperTest {
private UserRoleMapper userRoleMapper = Mappers.getMapper(UserRoleMapper.class);
@Test
public void testEntityToDto(){
String testDateStr = "2021-04-05T12:53:16.173706900";
LocalDateTime testDateLDT = LocalDateTime.parse(testDateStr);
UUID uuidTest = UUID.fromString("c095ad9f-37d4-479f-b88d-17df04f2437b");
UserRole e = new UserRole();
e.setName("Admin");
e.setDescription("Super");
e.setId(uuidTest);
e.setActiveFrom(testDateLDT);
e.setActiveUntil(testDateLDT);
e.setSystemProtectedStatus(true);
e.setBlockedStatus(false);
e.setSuspendedStatus(true);
e.setDeletedStatus(false);
e.setCreatedOn(testDateLDT);
e.setDeletedOn(testDateLDT);
e.setModifiedOn(testDateLDT);
List<SystemRights> eList = new ArrayList<>();
e.setSystemRights(eList);
SystemRights sr1= new SystemRights("Create");
SystemRights sr2= new SystemRights("Read");
SystemRights sr3= new SystemRights("Delete");
eList.add(sr1);
eList.add(sr2);
eList.add(sr3);
System.out.println("Testing testEntityToDto: Entity have");
System.out.println(e);
UserRoleDto d = userRoleMapper.getDtoFromEntity(e);
assertEquals(d.getName(),e.getName());
assertEquals(d.getDescription(),e.getDescription());
assertEquals(d.getId(),"c095ad9f-37d4-479f-b88d-17df04f2437b");
assertEquals(d.getActiveFrom(),"2021-04-05T12:53:16.173706900");
assertEquals(d.getActiveUntil(), "2021-04-05T12:53:16.173706900");
assertEquals(d.isSystemProtectedStatus(),e.isSystemProtectedStatus());
assertEquals(d.isDeletedStatus(),e.isDeletedStatus());
assertEquals(d.isBlockedStatus(),e.isBlockedStatus());
assertEquals(d.isSuspendedStatus(),e.isSuspendedStatus());
assertEquals(d.getCreatedOn(),"2021-04-05T12:53:16.173706900");
assertEquals(d.getModifiedOn(),"2021-04-05T12:53:16.173706900");
assertEquals(d.getDeletedOn(),"2021-04-05T12:53:16.173706900");
assertEquals(d.getSystemRightsDto().get(0).toString(),e.getSystemRights().get(0).toString());
assertEquals(d.getSystemRightsDto().get(1).toString(),e.getSystemRights().get(1).toString());
assertEquals(d.getSystemRightsDto().get(2).toString(),e.getSystemRights().get(2).toString());
assertEquals(d.getSystemRightsDto().toString(),e.getSystemRights().toString());
System.out.println("Testing testEntityToDto: Dto have");
System.out.println(d);
}
@Test
public void testDtoToEntity(){
String testDateStr = "2021-04-05T12:53:16.173706900";
LocalDateTime testDateLDT = LocalDateTime.parse(testDateStr);
UUID uuidTest = UUID.fromString("c095ad9f-37d4-479f-b88d-17df04f2437b");
UserRoleDto d = new UserRoleDto();
d.setName("Create");
d.setDescription("Desc");
d.setId("c095ad9f-37d4-479f-b88d-17df04f2437b");
d.setActiveFrom("2021-04-05T12:53:16.173706900");
d.setActiveUntil("2021-04-05T12:53:16.173706900");
d.setSystemProtectedStatus(true);
d.setBlockedStatus(false);
d.setSuspendedStatus(true);
d.setDeletedStatus(false);
d.setCreatedOn("2021-04-05T12:53:16.173706900");
d.setDeletedOn("2021-04-05T12:53:16.173706900");
d.setModifiedOn("2021-04-05T12:53:16.173706900");
List<SystemRightsDto> eListDto = new ArrayList<>();
d.setSystemRightsDto(eListDto);
SystemRightsDto sr1= new SystemRightsDto();
sr1.setName("Create");
SystemRightsDto sr2= new SystemRightsDto();
sr2.setName("Read");
SystemRightsDto sr3= new SystemRightsDto();
sr3.setName("Delete");
eListDto.add(sr1);
eListDto.add(sr2);
eListDto.add(sr3);
System.out.println("Testing testDtoToEntity: Dto have");
System.out.println(d);
UserRole e = userRoleMapper.getEntityFromDto(d);
assertEquals(e.getName(),d.getName());
assertEquals(e.getDescription(),d.getDescription());
assertEquals(e.getId(),uuidTest);
assertEquals(e.getActiveFrom(),testDateLDT);
assertEquals(e.getActiveUntil(),testDateLDT);
assertEquals(e.isSystemProtectedStatus(),d.isSystemProtectedStatus());
assertEquals(e.isDeletedStatus(),d.isDeletedStatus());
assertEquals(e.isBlockedStatus(),d.isBlockedStatus());
assertEquals(e.isSuspendedStatus(),d.isSuspendedStatus());
assertEquals(e.getCreatedOn(),testDateLDT);
assertEquals(e.getModifiedOn(),testDateLDT);
assertEquals(e.getDeletedOn(),testDateLDT);
assertEquals(e.getSystemRights().get(0).toString(),d.getSystemRightsDto().get(0).toString());
assertEquals(e.getSystemRights().get(1).toString(),d.getSystemRightsDto().get(1).toString());
assertEquals(e.getSystemRights().get(2).toString(),d.getSystemRightsDto().get(2).toString());
assertEquals(e.getSystemRights().toString(),d.getSystemRightsDto().toString());
System.out.println("Testing testDtoToEntity: Entity have");
System.out.println(e);
}
}
当我开始“TestEntityTodTo”测试时,我会发现:
测试TestEntityTodto:实体有UserRole(name=admin,description=super,SystemRights=[SystemRights(name=create,description=null)),SystemRights(name=delete,description=null)))
nullPointerException:无法调用“java.util.list.get(int)”,因为“com.example.cparty.dto.userroledto.getSystemRightSDTO()”的返回值为null
在com.example.cparty.userrolemappertest.TestEntityTodto(Userrolemappertest.java:77)
当我开始“TestDtotoEntity”测试时,我会发现:
测试TestDtoToEntity:Dto have UserRoleDto(名称=创建,描述=Desc,SystemRightsDto=[SystemRightsDto(Name=Create,Description=NULL),SystemRightsDto(Name=Read,Description=NULL)),SystemRightsDto(Name=Delete,Description=NULL))
java.lang.IndexOutOfBoundsException:索引0超出长度0的范围
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at com.example.cparty.UserRoleMapperTest.testDtoToEntity(UserRoleMapperTest.java:149)
MapStrakt本身生成了以下代码:(在其中,我没有看到它如何为目标对象设置列表)
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-04-06T11:03:58+0300",
comments = "version: 1.4.2.Final, compiler: javac, environment: Java 11.0.6 (JetBrains s.r.o)"
)
public class UserRoleMapperImpl implements UserRoleMapper {
@Override
public UserRoleDto getDtoFromEntity(UserRole entity) {
if ( entity == null ) {
return null;
}
UserRoleDto userRoleDto = new UserRoleDto();
userRoleDto.setSystemProtectedStatus( entity.isSystemProtectedStatus() );
userRoleDto.setSuspendedStatus( entity.isSuspendedStatus() );
userRoleDto.setBlockedStatus( entity.isBlockedStatus() );
userRoleDto.setDeletedStatus( entity.isDeletedStatus() );
userRoleDto.setName( entity.getName() );
userRoleDto.setDescription( entity.getDescription() );
userRoleDto.setId( getStringFromId(entity.getId()) );
userRoleDto.setActiveFrom( getStringfromLDT(entity.getActiveFrom()) );
userRoleDto.setActiveUntil( getStringfromLDT(entity.getActiveUntil()) );
userRoleDto.setCreatedOn( getStringfromLDT(entity.getCreatedOn()) );
userRoleDto.setModifiedOn( getStringfromLDT(entity.getModifiedOn()) );
userRoleDto.setDeletedOn( getStringfromLDT(entity.getDeletedOn()) );
return userRoleDto;
}
@Override
public UserRole getEntityFromDto(UserRoleDto dto) {
if ( dto == null ) {
return null;
}
UserRole userRole = new UserRole();
userRole.setSystemProtectedStatus( dto.isSystemProtectedStatus() );
userRole.setSuspendedStatus( dto.isSuspendedStatus() );
userRole.setBlockedStatus( dto.isBlockedStatus() );
userRole.setDeletedStatus( dto.isDeletedStatus() );
userRole.setName( dto.getName() );
userRole.setDescription( dto.getDescription() );
userRole.setId( getIdFromString(dto.getId()) );
userRole.setActiveFrom( getLDTfromString(dto.getActiveFrom()) );
userRole.setActiveUntil( getLDTfromString(dto.getActiveUntil()) );
userRole.setCreatedOn( getLDTfromString(dto.getCreatedOn()) );
userRole.setModifiedOn( getLDTfromString(dto.getModifiedOn()) );
userRole.setDeletedOn( getLDTfromString(dto.getDeletedOn()) );
return userRole;
}
@Override
public List<SystemRights> SystemRightsDtoToEnt(List<SystemRightsDto> dto) {
if ( dto == null ) {
return null;
}
List<SystemRights> list = new ArrayList<SystemRights>( dto.size() );
for ( SystemRightsDto systemRightsDto : dto ) {
list.add( systemRightsDtoToSystemRights( systemRightsDto ) );
}
return list;
}
@Override
public List<SystemRightsDto> SystemRightsEntToDto(List<SystemRights> entity) {
if ( entity == null ) {
return null;
}
List<SystemRightsDto> list = new ArrayList<SystemRightsDto>( entity.size() );
for ( SystemRights systemRights : entity ) {
list.add( systemRightsToSystemRightsDto( systemRights ) );
}
return list;
}
protected SystemRights systemRightsDtoToSystemRights(SystemRightsDto systemRightsDto) {
if ( systemRightsDto == null ) {
return null;
}
SystemRights systemRights = new SystemRights();
systemRights.setId( getIdFromString( systemRightsDto.getId() ) );
systemRights.setCreatedOn( getLDTfromString( systemRightsDto.getCreatedOn() ) );
systemRights.setModifiedOn( getLDTfromString( systemRightsDto.getModifiedOn() ) );
systemRights.setDeletedOn( getLDTfromString( systemRightsDto.getDeletedOn() ) );
systemRights.setSystemProtectedStatus( systemRightsDto.isSystemProtectedStatus() );
systemRights.setSuspendedStatus( systemRightsDto.isSuspendedStatus() );
systemRights.setBlockedStatus( systemRightsDto.isBlockedStatus() );
systemRights.setDeletedStatus( systemRightsDto.isDeletedStatus() );
systemRights.setActiveFrom( getLDTfromString( systemRightsDto.getActiveFrom() ) );
systemRights.setActiveUntil( getLDTfromString( systemRightsDto.getActiveUntil() ) );
systemRights.setName( systemRightsDto.getName() );
systemRights.setDescription( systemRightsDto.getDescription() );
return systemRights;
}
protected SystemRightsDto systemRightsToSystemRightsDto(SystemRights systemRights) {
if ( systemRights == null ) {
return null;
}
SystemRightsDto systemRightsDto = new SystemRightsDto();
systemRightsDto.setId( getStringFromId( systemRights.getId() ) );
systemRightsDto.setActiveFrom( getStringfromLDT( systemRights.getActiveFrom() ) );
systemRightsDto.setActiveUntil( getStringfromLDT( systemRights.getActiveUntil() ) );
systemRightsDto.setSystemProtectedStatus( systemRights.isSystemProtectedStatus() );
systemRightsDto.setSuspendedStatus( systemRights.isSuspendedStatus() );
systemRightsDto.setBlockedStatus( systemRights.isBlockedStatus() );
systemRightsDto.setDeletedStatus( systemRights.isDeletedStatus() );
systemRightsDto.setCreatedOn( getStringfromLDT( systemRights.getCreatedOn() ) );
systemRightsDto.setModifiedOn( getStringfromLDT( systemRights.getModifiedOn() ) );
systemRightsDto.setDeletedOn( getStringfromLDT( systemRights.getDeletedOn() ) );
systemRightsDto.setName( systemRights.getName() );
systemRightsDto.setDescription( systemRights.getDescription() );
return systemRightsDto;
}
}
好吧,也许问题出在我的环境中(整个pom.xml不适合):
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
<artifactId>spring-boot-starter-actuator</artifactId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<artifactId>spring-boot-starter-validation</artifactId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-devtools</artifactId>
<artifactId>postgresql</artifactId>
<artifactId>spring-boot-configuration-processor</artifactId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<artifactId>lombok-mapstruct-binding</artifactId>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<artifactId>spring-boot-starter-test</artifactId>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
当使用mapping#expression
,MapStruct将原样复制它,而不进行任何检查。
这个问题中有许多表达式
。我建议要么手工进行映射,要么让MapStruct来完成。
实际上,您可以删除所有@mapping
,并且一切都可以正常工作。
我如何在下面的场景中使用Mapstruct进行bean映射。 现在我想把sourceId映射到targetId,courseName映射到subjectName,studentName映射到memberName(list到list)。
我正在尝试映射我的遗留API对象(我无法更改它),该对象具有嵌套的原始类型属性。列表的元素与DTO列表的元素不兼容,应显式映射为嵌套。不幸的是,MapStruct似乎认为原始与所有类型化列表兼容,并忽略了我试图指定的任何映射,而生成的代码不能正常工作,随后在序列化程序的某个地方产生错误。 我的API对象具有嵌套的原始类型列表: 我的DTO对象具有DTO值类型元素的泛型类型列表: ...但MapSt
我尝试使用MapStruct编写映射器类,如下所示: 目前它显示了“未知属性”“customer.customerid”和“usertypes.usertype.userid”等错误。有人能帮我用MapStruct映射所有这些元素吗? 问题2:我们如何绘制跟踪图?1)customerId usertypes->user->userid 2)pdtPrice offers->OffersType->
我不确定如何将嵌套的结果集映射到域实体中。 以下是我想做的事情的大概想法: 2张桌子 域实体(包含嵌套列表) LoanEntity.java Book.java 持久实体 Loans.java Dao.xml(不知道如何映射它,尝试使用一个) 注意:此查询将复制找到的#本书的记录。 LoanMapper.java 下面的错误是我得到的: 错误:结果类型中的未知属性“books.bookName”c
我创建映射如下所示。如何将平面dto对象属性(街道、城市等)映射到域对象中的嵌套地址。当我试着去做的时候,我发现了一个错误: [错误]诊断:返回类型中的属性“Address.PostalCode”未知。@Mapping(来源=“City”,目标=“Address.City”), 还有类...
假设我有这些实体: null