MapStruct генерирует неправильный код отображения без какой-либо обратной конфигурации? - PullRequest
0 голосов
/ 04 марта 2020

У меня @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 с нежелательными отображениями в нем.

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!!!
    }
}

Что я сделал не так и как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 04 марта 2020

То, что вы называете нежелательным обратным отображением без каких-либо аннотаций, на самом деле является обычным способом генерации отображений MapStruct. Если исходный и целевой bean-компоненты имеют одно и то же свойство (как и в вашем случае), MapStruct создаст для него отображение.

В случае, если вы не хотите отображать некоторые свойства, вы можете либо игнорировать их, либо один или используйте @BeanMapping( ignoreByDefault = true). Со вторым параметром MapStruct будет создавать только сопоставления для определенного @Mapping.

0 голосов
/ 04 марта 2020

Я делюсь тем, что нашел.

Мне нужно было аннотировать метод с помощью @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);
}
...