Вопрос: Может ли mapstruct понять, что выражение возвращает строку, чтобы оно могло использовать мой формат данных, который я предоставляю?

#java #mapstruct

#java #mapstruct

Вопрос:

Я пытаюсь заставить Mapstruct понять, что исходное выражение — это строка, которую оно может форматировать в java.util.LocalDate, но я не уверен, что делаю это правильно. Я попытался следовать указаниям в документах mapstruct.

 @Mapping(componentModel = "cdi", uses=DateMapper.class)
public abstract class RedactedClassName

@Mapping(target = "birthDate",
            expression = "java(fileLine.substring(redactedpackagename.Constants.BIRTH_DATE_START_POS, redatcedpackagename.Constants.BIRTH_DATE_END_POS))")
    abstract PersonBio fileLineToPersonBio(String fileLine);
  

со следующим средством форматирования

 public class DateMapper {

    public String asString(LocalDate date) {

        return date != null ? date.format(DateTimeFormatter.ofPattern("yyyyMMdd")) : null;
    }

    public LocalDate asDate(String date) {
        return date != null ? LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyyMMdd")) : null;
    }
}
  

создает

     @Override
    PersonBio fileLineToPersonBio(String fileLine) {
        if ( fileLine == null ) {
            return null;
        }

        PersonBio personBio = new PersonBio();

        personBio.setBirthDate( fileLine.substring(redactedpackagename.Constants.BIRTH_DATE_START_POS, redactedpackagename.Constants.BIRTH_DATE_END_POS) );

        return personBio;
    }
  

Редактировать: Я немного изменил этот пост, чтобы, по моему мнению, он должен работать, но он все еще не работает.

Комментарии:

1. Тип вашего выражения не является LocalDate , это String . Сначала попробуйте использовать его в файле scratch Java, пока он не заработает.

2. Но дата рождения — это localdate, извините, забыл, что на самом деле здесь это не отображается.

3. Я обновил код, чтобы использовать пользовательский mapper, похоже, все еще не работает в соответствии со страницей инструкций mapstruct: mapstruct.org/documentation/stable/reference/html /…

Ответ №1:

Поскольку вывод вашего выражения java представляет собой строку, вы ожидаете, что mapstruct вызовет метод asDate класса DateMapper ?

То, что вы ожидаете иметь в сгенерированном коде, примерно так:

 ...
personBio.setBirthDate( new DateMapper().asDate(fileLine.substring(redactedpackagename.Constants.BIRTH_DATE_START_POS, redactedpackagename.Constants.BIRTH_DATE_END_POS)));
..
  

Вы правы, это не работает. Я не знаю почему…

Вместо этого вы можете импортировать mapper и использовать его в своем java-выражении и проверять входные данные с помощью StringUtils:

 @Mapper(imports = {DateMapper.class, StringUtils.class})
public interface PersonBioMapper {

  @Mapping(target = "birthDate",
      expression = "java(new DateMapper().asDate(StringUtils.substring(fileLine, redactedpackagename.Constants.BIRTH_DATE_START_POS, redatcedpackagename.Constants.BIRTH_DATE_END_POS)))")
  PersonBio fileLineToPersonBio(String fileLine);
}
  

Другой способ (более читаемый ?) как сказал Филип, сделайте пользовательское сопоставление:

 @Mapper
public interface PersonBioMapper {

  default PersonBio fileLineToPersonBio(String fileLine) {
    PersonBio personBio = new PersonBio();
    personBio.setBirthDate(new DateMapper().asDate(StringUtils.substring(fileLine,redactedpackagename.Constants.BIRTH_DATE_START_POS, redactedpackagename.Constants.BIRTH_DATE_END_POS)));

    return personBio;
  }
}
  

Ответ №2:

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

Я бы попытался подойти к проблеме, которую вы пытаетесь решить, с другой стороны. Вместо использования выражения используйте для него пользовательское сопоставление, которое создаст дату из строки.

Вы можете прочитать больше об этом выражении в разделе «Выражения» документации.