Сопоставить нулевые значения со значениями по умолчанию с помощью компоновщика с MapStruct - PullRequest
0 голосов
/ 27 марта 2020

Я хочу отобразить поле из Source в Target класс, и если исходное значение равно null, я хотел бы преобразовать его в значение по умолчанию на основе типа данных ("" для строк, 0 для цифры c и т. д. c.). Для установки значений я использую не обычные сеттеры, а компоновщик (с protobuf , поэтому имена методов - newBuilder() и build()).

class Source {
    private final String value; // getter
}

class Target {
    private final String value;

    public static Builder newBuilder() {return new Builder()}

    public static class Builder {
        public static setValue() {/*Set the field*/}
        public static Target build() {/*Return the constructed instance*/}
}

My mapper выглядит следующим образом:

@Mapper(
    nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT,
    nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT
)
public interface TargetMapper {
    Target map(Source source);
}

Сгенерированная реализация mapper с этим кодом вызывает target.setValue(source.getValue()) вместо выполнения нулевой проверки и установки значения по умолчанию, если источник возвращает null. Интересная часть заключается в том, что когда я добавляю следующую аннотацию к методу map, в реализации присутствует пустая проверка.

@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)

Это ошибка в MapStruct со сборщиками или я пропустил некоторую конфигурацию чтобы можно было установить нулевое сопоставление в качестве политики по умолчанию, вместо того, чтобы дублировать его на всех сопоставлениях полей?

РЕДАКТИРОВАТЬ: По какой-то причине добавление nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS к аннотации @Mapper уровня класса добавляет проверку нуля , но явно не устанавливает значение, просто пропускает вызов setValue. Для protobuf это нормально, поскольку эта функциональность есть в библиотеке, но для других реализаций поле останется нулевым.

1 Ответ

1 голос
/ 05 апреля 2020

@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)

применяется к методу обновления (поэтому методы с аннотированным параметром @MappingTarget

Для обычных методов нет реального аналога: 1. NullValueMappingStragegy применяется к бобу сам аргумент. 2. NullValueCheckStragegy выполняет проверку свойств bean-компонента, но не возвращает значение по умолчанию.

Именование не является действительно блестящим и имеет длинную историю. У нас все еще есть намерение выровнять это день.

Решением было бы использование фабрики объектов, создающей целевой объект построителя и предварительно заполняющей его значениями по умолчанию, а затем позволяющей MapStuct переопределить эти один день.

Возможно, вы могли бы что-то сделать как это:

@Mapper(
    // to perform a null check
    nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
)
public interface TargetMapper {
    Target map(Source source);
}

// to create a pre-defined object (defaults set a-priori). Not sure
// whether this works with builders.. just try
@ObjectFactory
default Target.Builder create() {

   Target.Builder builder = Target.newBuilder();
   builder.setValueX( "someDefaultValue" );
   return builder;

}
...