mapstruct双向Map

kzmpq1sx  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(686)

在下面的例子中,我有一个单独的域层和一个单独的持久层。我使用mapstruct进行Map,当从域Map到实体或从实体Map到域时,会出现stackoverflow,因为在->无限循环场景中总是调用双向引用。如何在此场景中使用mapstruct?

class User {
  private UserProfile userProfile;
}

class UserProfile {
 private User user;
}

@Entity
class UserEntity {
  @OneToOne
  @PrimaryKeyJoinColumn
  private UserProfileEntity userProfile;
}

@Entity
class UserProfileEntity {
  @OneToOne(mappedBy = "userProfile")
  private UserEntity userEntity;
}

用于Map的类非常基本

@Mapper
interface UserMapper {

UserEntity mapToEntity(User user);

User mapToDomain(UserEntity userEntity);
}
tv6aics1

tv6aics11#

查看mapstructMapwith cycles示例。
上下文注解的文档中还演示了问题的解决方案。

示例

一个完整的例子:https://github.com/jannis-baratheon/stackoverflow--mapstruct-mapping-graph-with-cycles.

参考

Map器:

@Mapper
public interface UserMapper {

    @Mapping(target = "userProfileEntity", source = "userProfile")
    UserEntity mapToEntity(User user,
                           @Context CycleAvoidingMappingContext cycleAvoidingMappingContext);

    @InheritInverseConfiguration
    User mapToDomain(UserEntity userEntity,
                     @Context CycleAvoidingMappingContext cycleAvoidingMappingContext);

    @Mapping(target = "userEntity", source = "user")
    UserProfileEntity mapToEntity(UserProfile userProfile,
                                  @Context CycleAvoidingMappingContext cycleAvoidingMappingContext);

    @InheritInverseConfiguration
    UserProfile mapToDomain(UserProfileEntity userProfileEntity,
                            @Context CycleAvoidingMappingContext cycleAvoidingMappingContext);
}

哪里 CycleAvoidingMappingContext 跟踪已Map的对象并重用它们,以避免堆栈溢出:

public class CycleAvoidingMappingContext {
    private final Map<Object, Object> knownInstances = new IdentityHashMap<>();

    @BeforeMapping
    public <T> T getMappedInstance(Object source,
                                   @TargetType Class<T> targetType) {
        return targetType.cast(knownInstances.get(source));
    }

    @BeforeMapping
    public void storeMappedInstance(Object source,
                                    @MappingTarget Object target) {
        knownInstances.put(source, target);
    }
}

Map器用法(Map单个对象):

UserEntity mappedUserEntity = mapper.mapToEntity(user, new CycleAvoidingMappingContext());

也可以在Map器上添加默认方法:

@Mapper
public interface UserMapper {

    // (...)

    default UserEntity mapToEntity(User user) {
        return mapToEntity(user, new CycleAvoidingMappingContext());
    }

    // (...)
}

相关问题