MapStruct 在没有任何反向配置的情况下生成错误的映射代码?
MapStruct generates wrong mapping code without any inverse config?
我有一个 @MapperConfig
看起来像这样。
@MapperConfig(componentModel = "spring")
public interface SomeEntityTypeMapperConfig {
@Mapping(target = PROPERTY_NAME_ENTITY)
@Mapping(source = SomeEntity.ATTRIBUTE_NAME_ID, target = SomeEntityType.PROPERTY_NAME_ID)
@Mapping(source = SomeEntity.PROPERTY_NAME_CREATED_AT, target = SomeEntityType.PROPERTY_NAME_CREATED_AT)
@Mapping(source = SomeEntity.PROPERTY_NAME_UPDATED_AT, target = SomeEntityType.PROPERTY_NAME_UPDATED_AT)
@Mapping(source = SomeEntity.PROPERTY_NAME_CREATED_BY, target = SomeEntityType.PROPERTY_NAME_CREATED_BY)
@Mapping(source = SomeEntity.PROPERTY_NAME_UPDATED_BY, target = SomeEntityType.PROPERTY_NAME_UPDATED_BY)
SomeEntityType<?, ?> fromEntity(SomeEntity entity);
// No @Mapping
void toEntity(SomeEntityType<?, ?> type, @MappingTarget SomeEntity entity);
}
这是我的基本映射器界面。
public interface SomeEntityTypeMapper<T extends SomeEntityType<?, U>, U extends SomeEntity> {
T fromEntity(U entity);
void toEntity(T type, @MappingTarget U entity);
}
我真正的制图器来了。
@Mapper(config = SomeEntityTypeMapperConfig.class)
public interface UserTypeMapper extends SomeEntityTypeMapper<UserType, User> {
@Mapping(source = User.ATTRIBUTE_NAME_NAME, target = UserType.PROPERTY_NAME_NAME)
@Override
UserType fromEntity(User entity);
@Mapping(source = UserType.PROPERTY_NAME_NAME, target = User.ATTRIBUTE_NAME_NAME)
@Override
void toEntity(UserType type, @MappingTarget User entity);
}
并且 MapStruct 生成以下 impl class,其中包含不需要的映射。
public class UserTypeMapperImpl implements UserTypeMapper {
@Override
public UserType fromEntity(User entity) {
if ( entity == null ) {
return null;
}
UserType userType = new UserType();
userType.setName( entity.getName() ); // explicitly configured
userType.setId( entity.getId() ); // inherited from the config
userType.setCreatedAt( entity.getCreatedAt() ); // inherited from the config
userType.setUpdatedAt( entity.getUpdatedAt() ); // inherited from the config
userType.setCreatedBy( entity.getCreatedBy() ); // inherited from the config
userType.setUpdatedBy( entity.getUpdatedBy() ); // inherited from the config
return userType;
}
@Override
public void toEntity(UserType type, User entity) {
if ( type == null ) {
return;
}
entity.setName( type.getName() ); // explicitly configured
entity.setCreatedAt( type.getCreatedAt() ); // UNWANTED!!!
entity.setUpdatedAt( type.getUpdatedAt() ); // UNWANTED!!!
entity.setUpdatedBy( type.getUpdatedBy() ); // UNWANTED!!!
entity.setId( type.getId() ); // UNWANTED!!!
entity.setCreatedBy( type.getCreatedBy() ); // UNWANTED!!!
}
}
我做错了什么,我该如何解决?
我正在分享我的发现。
我需要用 @BeanMapping(ignoreByDefault = true)
注释该方法。
有趣的是,注释必须位于叶映射器接口中。
@BeanMapping(ignoreByDefault = true) // WORKS!!!
@Mapping(source = UserType.PROPERTY_NAME_NAME, target = User.ATTRIBUTE_NAME_NAME)
@Override
void toEntity(UserType type, @MappingTarget User entity);
不适用于配置或父界面。
public interface SomeEntityTypeMapperConfig {
@BeanMapping(ignoreByDefault = true) // Doesn't work!
void toEntity(SomeEntityType<?, ?> type, @MappingTarget SomeEntity entity);
}
public interface SomeEntityTypeMapper<T extends SomeEntityType<?, U>, U extends SomeEntity> {
@BeanMapping(ignoreByDefault = true) // Doesn't work!
void toEntity(T type, @MappingTarget U entity);
}
你所说的没有任何注释的不需要的反向映射实际上是 MapStruct 生成映射的正常方式。如果源 bean 和目标 bean 具有相同的 属性(它们在您的情况下也是如此),MapStruct 将为它创建一个映射。
如果您不想映射某些属性,您可以一一忽略它们或使用 @BeanMapping( ignoreByDefault = true)
。使用第二个选项 MapStruct 只会为定义的 @Mapping
.
创建映射
我有一个 @MapperConfig
看起来像这样。
@MapperConfig(componentModel = "spring")
public interface SomeEntityTypeMapperConfig {
@Mapping(target = PROPERTY_NAME_ENTITY)
@Mapping(source = SomeEntity.ATTRIBUTE_NAME_ID, target = SomeEntityType.PROPERTY_NAME_ID)
@Mapping(source = SomeEntity.PROPERTY_NAME_CREATED_AT, target = SomeEntityType.PROPERTY_NAME_CREATED_AT)
@Mapping(source = SomeEntity.PROPERTY_NAME_UPDATED_AT, target = SomeEntityType.PROPERTY_NAME_UPDATED_AT)
@Mapping(source = SomeEntity.PROPERTY_NAME_CREATED_BY, target = SomeEntityType.PROPERTY_NAME_CREATED_BY)
@Mapping(source = SomeEntity.PROPERTY_NAME_UPDATED_BY, target = SomeEntityType.PROPERTY_NAME_UPDATED_BY)
SomeEntityType<?, ?> fromEntity(SomeEntity entity);
// No @Mapping
void toEntity(SomeEntityType<?, ?> type, @MappingTarget SomeEntity entity);
}
这是我的基本映射器界面。
public interface SomeEntityTypeMapper<T extends SomeEntityType<?, U>, U extends SomeEntity> {
T fromEntity(U entity);
void toEntity(T type, @MappingTarget U entity);
}
我真正的制图器来了。
@Mapper(config = SomeEntityTypeMapperConfig.class)
public interface UserTypeMapper extends SomeEntityTypeMapper<UserType, User> {
@Mapping(source = User.ATTRIBUTE_NAME_NAME, target = UserType.PROPERTY_NAME_NAME)
@Override
UserType fromEntity(User entity);
@Mapping(source = UserType.PROPERTY_NAME_NAME, target = User.ATTRIBUTE_NAME_NAME)
@Override
void toEntity(UserType type, @MappingTarget User entity);
}
并且 MapStruct 生成以下 impl class,其中包含不需要的映射。
public class UserTypeMapperImpl implements UserTypeMapper {
@Override
public UserType fromEntity(User entity) {
if ( entity == null ) {
return null;
}
UserType userType = new UserType();
userType.setName( entity.getName() ); // explicitly configured
userType.setId( entity.getId() ); // inherited from the config
userType.setCreatedAt( entity.getCreatedAt() ); // inherited from the config
userType.setUpdatedAt( entity.getUpdatedAt() ); // inherited from the config
userType.setCreatedBy( entity.getCreatedBy() ); // inherited from the config
userType.setUpdatedBy( entity.getUpdatedBy() ); // inherited from the config
return userType;
}
@Override
public void toEntity(UserType type, User entity) {
if ( type == null ) {
return;
}
entity.setName( type.getName() ); // explicitly configured
entity.setCreatedAt( type.getCreatedAt() ); // UNWANTED!!!
entity.setUpdatedAt( type.getUpdatedAt() ); // UNWANTED!!!
entity.setUpdatedBy( type.getUpdatedBy() ); // UNWANTED!!!
entity.setId( type.getId() ); // UNWANTED!!!
entity.setCreatedBy( type.getCreatedBy() ); // UNWANTED!!!
}
}
我做错了什么,我该如何解决?
我正在分享我的发现。
我需要用 @BeanMapping(ignoreByDefault = true)
注释该方法。
有趣的是,注释必须位于叶映射器接口中。
@BeanMapping(ignoreByDefault = true) // WORKS!!!
@Mapping(source = UserType.PROPERTY_NAME_NAME, target = User.ATTRIBUTE_NAME_NAME)
@Override
void toEntity(UserType type, @MappingTarget User entity);
不适用于配置或父界面。
public interface SomeEntityTypeMapperConfig {
@BeanMapping(ignoreByDefault = true) // Doesn't work!
void toEntity(SomeEntityType<?, ?> type, @MappingTarget SomeEntity entity);
}
public interface SomeEntityTypeMapper<T extends SomeEntityType<?, U>, U extends SomeEntity> {
@BeanMapping(ignoreByDefault = true) // Doesn't work!
void toEntity(T type, @MappingTarget U entity);
}
你所说的没有任何注释的不需要的反向映射实际上是 MapStruct 生成映射的正常方式。如果源 bean 和目标 bean 具有相同的 属性(它们在您的情况下也是如此),MapStruct 将为它创建一个映射。
如果您不想映射某些属性,您可以一一忽略它们或使用 @BeanMapping( ignoreByDefault = true)
。使用第二个选项 MapStruct 只会为定义的 @Mapping
.