假设我有这样的映射:
function changeFormat($js)
{
$jsArray = json_decode($js,true);
$result = array();
foreach($jsArray as $key=>$value)
{
$result[] = array("label"=>$key,"value"=>$value);
}
return json_encode($result);
}
echo changeFormat($js);
现在我需要将ChildDto列表映射到Child列表,但它们都具有相同的父级。我期望做类似的事情:
@Mapping(source = "parentId", target = "parent.id")
Child map(ChildDto dto, Parent parent);
但它不起作用。 有没有机会这样做?
答案 0 :(得分:2)
我找到了如何使用装饰器实现它,感谢@Gunnar 这是一个实现:
public class Child {
int id;
String name;
}
public class Parent {
int id;
String name;
}
public class ChildDto {
int id;
String name;
int parentId;
String parentName;
}
// getters/settes ommited
@Mapper
@DecoratedWith(ChildMapperDecorator.class)
public abstract class ChildMapper {
public static final ChildMapper INSTANCE = Mappers.getMapper(ChildMapper.class);
@Mappings({
@Mapping(target = "parentId", ignore = true),
@Mapping(target = "parentName", ignore = true)
})
@Named("toDto")
abstract ChildDto map(Child child);
@Mappings({
@Mapping(target = "id", ignore = true),
@Mapping(target = "name", ignore = true),
@Mapping(target = "parentId", source = "id"),
@Mapping(target = "parentName", source = "name")
})
abstract ChildDto map(@MappingTarget ChildDto dto, Parent parent);
@IterableMapping(qualifiedByName = "toDto") // won't work without it
abstract List<ChildDto> map(List<Child> children);
List<ChildDto> map(List<Child> children, Parent parent) {
throw new UnsupportedOperationException("Not implemented");
}
}
public abstract class ChildMapperDecorator extends ChildMapper {
private final ChildMapper delegate;
protected ChildMapperDecorator(ChildMapper delegate) {
this.delegate = delegate;
}
@Override
public List<ChildDto> map(List<Child> children, Parent parent) {
List<ChildDto> dtoList = delegate.map(children);
for (ChildDto childDto : dtoList) {
delegate.map(childDto, parent);
}
return dtoList;
}
}
我使用abstract class
而非interface
用于映射器,因为在interface
的情况下,您无法排除生成方法map(List<Child> children, Parent parent)
,并且生成的代码不是在编译时有效。
答案 1 :(得分:1)
事情的发展并不是开箱即用的。您可以使用装饰器或后映射方法将父级设置为之后的所有子对象。
答案 2 :(得分:1)
我使用了Gunnar建议的@AfterMapping
:
@AfterMapping
public void afterDtoToEntity(final QuestionnaireDTO dto, @MappingTarget final Questionnaire entity) {
entity.getQuestions().stream().forEach(question -> question.setQuestionnaire(entity));
}
这确保所有问题都与同一个问卷实体相关联。这是解决方案的最后一部分,用于避免在创建带有子列表的新父实体时出现JPA错误save the transient instance before flushing
。