有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在Mapstruct中使用双向实体方法

我有双向映射(@OneToMany Hibernate)和额外的方法来确保两个对象链接。 简单的例子:

@Setter
class ParentDto {
    List<ChildDto> childList;
}

@Setter
class ChildDto {
    String text;
}

@Setter
class Parent {

    List<Child> childList;

    public void addChild(Child child) {
        childList.add(child);
        child.setParent(this);
    }
}

@Setter
class Child {
    Parent parent;
    String text;
}

制图员:

@Mapper(componentModel = "spring")
public interface TestMapper {

Parent toEntity(ParentDto parentDto);
}

生成:

public class TestMapperImpl implements TestMapper {

@Override
public Parent toEntity(ParentDto parentDto) {
    if ( parentDto == null ) {
        return null;
    }

    Parent parent = new Parent();
    parent.setChildList( childDtoListToChildList( parentDto.getChildList() ) );

    return parent;
}

protected Child childDtoToChild(ChildDto childDto) {
    if ( childDto == null ) {
        return null;
    }

    Child child = new Child();
    child.setText( childDto.getText() );

    return child;
}

protected List<Child> childDtoListToChildList(List<ChildDto> list) {
    if ( list == null ) {
        return null;
    }

    List<Child> list1 = new ArrayList<Child>( list.size() );
    for ( ChildDto childDto : list ) {
        list1.add( childDtoToChild( childDto ) );
    }
    return list1;
}

主要问题:如何强制Mapstruct使用parent.addChild (...)来保持父对象和子对象列表之间的双向映射

我有一个更复杂的结构,有多个嵌套的子级,所以要考虑可扩展性


共 (2) 个答案

  1. # 1 楼答案

    经过长时间的寻找,我找到了迄今为止最好的解决方案。它不使用特殊方法,但允许您维护双向连接

    @AfterMapping
    default void mapBidirectional(@MappingTarget Parent parent){
        List<Child> childList = parent.getChildList();
        if (childList != null) {
            childList.forEach(child -> child.setParent(parent));
        }
    }
    

    将会是

    @Override
    public Parent toEntity(ParentDto parentDto) {
        if ( parentDto == null ) {
            return null;
        }
    
        Parent parent = new Parent();
    
        parent.setChildList( childDtoListToChildList( parentDto.getChildList() ) );
    
        mapBidirectional( parent );
    
        return parent;
    }
    

    但这个问题很可能还有另一种解决方案,因为双向通信非常常见,而且这个解决方案的扩展性不好

    而且它不能被拆分成几个*映射类,因为不能在@AfterMapping方法中使用生成的变量

  2. # 2 楼答案

    MapStruct的概念是Collection Mapping Strategies。它允许您在映射它们时使用加法器

    例如

    @Mapper(componentModel = "spring", collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
    public interface TestMapper {
    
        Parent toEntity(ParentDto parentDto);
    }