我有两个具有一对多关系的实体,如下所示:
public class ParentEntity {
private Long id;
private String name;
private List<ChildEntity> children;
//getters/setters
}
public class ChildEntity {
private Long id;
private String name;
private ParentEntity myParent;
private String notMappedField1;
private Long notMappedField2;
//getters/setters
}
和DTO
public class ParentDTO {
private Long id;
private String name;
private List<ChildDto> children;
//getters/setters
}
public class ChildDto {
private Long id;
private String name;
private ParentDto myParent;
//getters/setters
}
使用Mapstruct注释我创建了两个映射器,每个实体一个:
@Mapper(componentModel = "cdi", uses = {ChildMapper.class})
public interface ParentMapper {
ParentDto toDto(ParentEntity entity);
ParentEntity toEntity(ParentDto s);
ParentEntity toEntity(ParentDto s, @MappingTarget ParentEntity entity);
}
@Mapper(componentModel = "cdi")
public interface ChildMapper {
ChildDto toDto(ChildEntity entity);
@Mapping(target = "myParent", ignore = true)
ChildEntity toEntity(ChildDto s);
@InheritConfiguration
ChildEntity toEntity(ChildDto s, @MappingTarget ChildEntity entity);
}
生成的父映射器如下:
@ApplicationScoped
public class ParentMapperImpl implements ParentMapper {
@Inject
private ChildMapper childMapper;
@Override
public ParentDto toDto(ParentEntity entity) {
if ( entity == null ) {
return null;
}
ParentDto parentDto = new ParentDto();
parentDto.setId( entity.getId() );
parentDto.setName( entity.getName() );
parentDto.setChildren( childEntityListToChildDtoList( entity.getChildren() ) );
return parentDto;
}
@Override
public ParentEntity toEntity(ParentDto s) {
if ( s == null ) {
return null;
}
ParentEntity parentEntity = new ParentEntity();
parentEntity.setId( s.getId() );
parentEntity.setName( s.getName() );
parentEntity.setChildren( childDtoListToChildEntityList( s.getChildren() ) );
return parentEntity;
}
@Override
public ParentEntity toEntity(ParentDto s, ParentEntity entity) {
if ( s == null ) {
return null;
}
entity.setId( s.getId() );
entity.setName( s.getName() );
if ( entity.getChildren() != null ) {
List<ChildEntity> list = childDtoListToChildEntityList( s.getChildren() );
if ( list != null ) {
entity.getChildren().clear();
entity.getChildren().addAll( list );
}
else {
entity.setChildren( null );
}
}
else {
List<ChildEntity> list = childDtoListToChildEntityList( s.getChildren() );
if ( list != null ) {
entity.setChildren( list );
}
}
return entity;
}
protected List<ChildDto> childEntityListToChildDtoList(List<ChildEntity> list) {
if ( list == null ) {
return null;
}
List<ChildDto> list1 = new ArrayList<ChildDto>( list.size() );
for ( ChildEntity childEntity : list ) {
list1.add( childMapper.toDto( childEntity ) );
}
return list1;
}
protected List<ChildEntity> childDtoListToChildEntityList(List<ChildDto> list) {
if ( list == null ) {
return null;
}
List<ChildEntity> list1 = new ArrayList<ChildEntity>( list.size() );
for ( ChildDto childDto : list ) {
list1.add( childMapper.toEntity( childDto ) );
}
return list1;
}
}
但是当调用ParentMapper.toEntity(ParentDto s, ParentEntity entity)
时,
在子映射器上称为ChildMapper.toEntity(ChildDto s)
。
相反,我希望调用以下子映射器方法ChildMapper.toEntity(ChildDto s, ChildEntity entity)
,
合并现有的子实体(假设我们有其他字段)
不存在于我们不想丢失的Dto中的子实体
期望的结果如下,或类似的东西:
@ApplicationScoped
public class ParentMapperImpl implements ParentMapper {
...
@Override
public ParentEntity toEntity(ParentDto s, ParentEntity entity) {
if (s == null) {
return null;
}
entity.setId(s.getId());
entity.setName(s.getName());
if (entity.getChildren() != null) {
List<ChildEntity> list = childDtoListToChildEntityList(s.getChildren(), entity.getChildren());
if (list != null) {
entity.getChildren().clear();
entity.getChildren().addAll(list);
} else {
entity.setChildren(null);
}
} else {
List<ChildEntity> list = childDtoListToChildEntityList(s.getChildren());
if (list != null) {
entity.setChildren(list);
}
}
return entity;
}
...
protected List<ChildEntity> childDtoListToChildEntityList(List<ChildDto> list, List<ChildEntity> entities) {
if (list == null) {
return null;
}
final List<ChildEntity> list1 = new ArrayList<ChildEntity>(list.size());
for (ChildEntity entity : entities) {
Optional<ChildEntity> optional = findEntity(entity.getId(), list);
if (optional.isPresent()) {
list1.add(childMapper.toEntity(optional.get(), entity));
}
}
list1.addAll(
list.stream()
.filter(dto -> dto.getId() == null)
.map(dto -> childMapper.toEntity(dto))
.collect(Collectors.toList())
);
return list1;
}
private Optional<ChildEntity> findEntity(Long id, List<ChildDto> list) {
return list.stream().filter(dto -> dto.getId().equals(id)).findAny();
}
}
答案 0 :(得分:1)
我的porpouse是通过合并现有的子实体来执行一对多实体关系的更新,假设我们在Dto中不存在的子实体上有其他字段我们不想丢失。
我有两个具有一对多关系的实体,如下所示:
public class ParentEntity {
private Long id;
private String name;
private List<ChildEntity> children;
//getters/setters
}
public class ChildEntity {
private Long id;
private String name;
private ParentEntity myParent;
private String notMappedField1;
private Long notMappedField2;
//getters/setters
}
和DTO
public class ParentDTO {
private Long id;
private String name;
private List<ChildDto> children;
//getters/setters
}
public class ChildDto {
private Long id;
private String name;
private ParentDto myParent;
//getters/setters
}
使用Mapstruct注释我创建了两个映射器,每个实体一个:
@Mapper(componentModel = "cdi", uses = {ChildMapper.class})
public interface ParentMapper {
ParentDto toDto(ParentEntity entity);
ParentEntity toEntity(ParentDto s);
ParentEntity toEntity(ParentDto s, @MappingTarget ParentEntity entity);
}
@Mapper(componentModel = "cdi")
public interface ChildMapper {
ChildDto toDto(ChildEntity entity);
@Mapping(target = "myParent", ignore = true)
ChildEntity toEntity(ChildDto s);
@InheritConfiguration
ChildEntity toEntity(ChildDto s, @MappingTarget ChildEntity entity);
}
生成的父映射器如下:
@ApplicationScoped
public class ParentMapperImpl implements ParentMapper {
@Inject
private ChildMapper childMapper;
@Override
public ParentDto toDto(ParentEntity entity) {
if ( entity == null ) {
return null;
}
ParentDto parentDto = new ParentDto();
parentDto.setId( entity.getId() );
parentDto.setName( entity.getName() );
parentDto.setChildren( childEntityListToChildDtoList( entity.getChildren() ) );
return parentDto;
}
@Override
public ParentEntity toEntity(ParentDto s) {
if ( s == null ) {
return null;
}
ParentEntity parentEntity = new ParentEntity();
parentEntity.setId( s.getId() );
parentEntity.setName( s.getName() );
parentEntity.setChildren( childDtoListToChildEntityList( s.getChildren() ) );
return parentEntity;
}
@Override
public ParentEntity toEntity(ParentDto s, ParentEntity entity) {
if ( s == null ) {
return null;
}
entity.setId( s.getId() );
entity.setName( s.getName() );
if ( entity.getChildren() != null ) {
List<ChildEntity> list = childDtoListToChildEntityList( s.getChildren() );
if ( list != null ) {
entity.getChildren().clear();
entity.getChildren().addAll( list );
}
else {
entity.setChildren( null );
}
}
else {
List<ChildEntity> list = childDtoListToChildEntityList( s.getChildren() );
if ( list != null ) {
entity.setChildren( list );
}
}
return entity;
}
protected List<ChildDto> childEntityListToChildDtoList(List<ChildEntity> list) {
if ( list == null ) {
return null;
}
List<ChildDto> list1 = new ArrayList<ChildDto>( list.size() );
for ( ChildEntity childEntity : list ) {
list1.add( childMapper.toDto( childEntity ) );
}
return list1;
}
protected List<ChildEntity> childDtoListToChildEntityList(List<ChildDto> list) {
if ( list == null ) {
return null;
}
List<ChildEntity> list1 = new ArrayList<ChildEntity>( list.size() );
for ( ChildDto childDto : list ) {
list1.add( childMapper.toEntity( childDto ) );
}
return list1;
}
}
出现在我脑海中的第一个解决方案是通过合并子dto列表和子实体列表来执行子实体列表的更新,所以当我调用ParentMapper.toEntity(ParentDto s, ParentEntity entity)
时,孩子映射器必须调用方法ChildMapper.toEntity(ChildDto s, ChildEntity entity)
来合并现有的子实体,而不是这个实体ChildMapper.toEntity(ChildDto s)
所以结果可能是以下,或类似的东西:
@ApplicationScoped
public class ParentMapperImpl implements ParentMapper {
...
@Override
public ParentEntity toEntity(ParentDto s, ParentEntity entity) {
if (s == null) {
return null;
}
entity.setId(s.getId());
entity.setName(s.getName());
if (entity.getChildren() != null) {
List<ChildEntity> list = childDtoListToChildEntityList(s.getChildren(), entity.getChildren());
if (list != null) {
entity.getChildren().clear();
entity.getChildren().addAll(list);
} else {
entity.setChildren(null);
}
} else {
List<ChildEntity> list = childDtoListToChildEntityList(s.getChildren());
if (list != null) {
entity.setChildren(list);
}
}
return entity;
}
...
protected List<ChildEntity> childDtoListToChildEntityList(List<ChildDto> list, List<ChildEntity> entities) {
if (list == null) {
return null;
}
final List<ChildEntity> list1 = new ArrayList<ChildEntity>(list.size());
for (ChildEntity entity : entities) {
Optional<ChildEntity> optional = findEntity(entity.getId(), list);
if (optional.isPresent()) {
list1.add(childMapper.toEntity(optional.get(), entity));
}
}
list1.addAll(
list.stream()
.filter(dto -> dto.getId() == null)
.map(dto -> childMapper.toEntity(dto))
.collect(Collectors.toList())
);
return list1;
}
private Optional<ChildEntity> findEntity(Long id, List<ChildDto> list) {
return list.stream().filter(dto -> dto.getId().equals(id)).findAny();
}
}
这对Mapstruct来说是否可行? 有没有其他方法来更新与Mapstruct的孩子关系?
答案 1 :(得分:0)
目前无法做到这一点。对此已经存在一个悬而未决的问题。看看487。
执行2个列表的合并并非易事。它需要MapStruct知道如何生成该find方法。