[英]Mapstruct bidirectional mapping
I have the following example in which i have a separate domain layer and a separate persistence layer.我有以下示例,其中我有一个单独的域层和一个单独的持久层。 I am using Mapstruct for mapping and I get StackOverflow when mapping from domain to entity or from entity to domain because of the bidirectional reference that always gets called on -> infinite loop scenario.我使用 Mapstruct 进行映射,当从域映射到实体或从实体映射到域时,我得到 StackOverflow,因为双向引用总是被调用 -> 无限循环场景。 How can I use Mapstruct for this scenario?如何在这种情况下使用 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;
}
class for mapping is pretty basic映射类非常基础
@Mapper
interface UserMapper {
UserEntity mapToEntity(User user);
User mapToDomain(UserEntity userEntity);
}
Check out the Mapstruct mapping with cycles example.查看带有循环示例的Mapstruct 映射。
A solution to your problem is also demonstrated in the documentation for Context annotation .您的问题的解决方案也在Context annotation 的文档中进行了演示。
A complete example: https://github.com/jannis-baratheon/stackoverflow--mapstruct-mapping-graph-with-cycles .一个完整的例子: https : //github.com/jannis-baratheon/stackoverflow--mapstruct-mapping-graph-with-cycles 。
Mapper:映射器:
@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);
}
where CycleAvoidingMappingContext
keeps track of the already mapped objects and reuses them avoiding the stack overflow:其中CycleAvoidingMappingContext
跟踪已映射的对象CycleAvoidingMappingContext
它们以避免堆栈溢出:
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);
}
}
Mapper usage (mapping single object):映射器用法(映射单个对象):
UserEntity mappedUserEntity = mapper.mapToEntity(user, new CycleAvoidingMappingContext());
You can also add a default method on your mapper:您还可以在映射器上添加默认方法:
@Mapper
public interface UserMapper {
// (...)
default UserEntity mapToEntity(User user) {
return mapToEntity(user, new CycleAvoidingMappingContext());
}
// (...)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.