#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 не проверяет выражение во время генерации. Это означает, что вы должны убедиться, что ваше выражение выводит допустимый код.
Я бы попытался подойти к проблеме, которую вы пытаетесь решить, с другой стороны. Вместо использования выражения используйте для него пользовательское сопоставление, которое создаст дату из строки.
Вы можете прочитать больше об этом выражении в разделе «Выражения» документации.