Я довольно долго смотрю на эту проблему и не могу найти ответ.Я пытаюсь использовать mapstruct для отображения объектов, у которых есть поля, которые являются реализациями универсальных объектов SingleValue.
Позвольте мне проиллюстрировать проблему на упрощенном примере.(броски опущены для читабельности)
У нас есть объект Single Value:
public abstract class SingleValue<T extends Serializable> implements Serializable {
private T value;
public SingleValue(T value) {
this.value = value;
}
}
Конкретный класс Single Value будет выглядеть следующим образом
public class FirstName extends SingleValue<String>{
}
И будетиспользуется в различных объектах, которые могут быть сопоставлены друг с другом
Отображения, которые должны быть возможны:
- String -> FirstName
- FirstName -> String
- FirstName -> еще один расширяет объект SingleValue
Возможны следующие сопоставления с текущим решением:
- String -> FirstName
- FirstName ->Строка
Текущее сопоставление одного значения
@Mapper
public interface SingleValueMapper {
SingleValueMapper INSTANCE = Mappers.getMapper(SingleValueMapper.class);
default <Z extends Serializable, T extends SingleValue<Z>> T singleValue(Z obj, Class<Z> objClass, @TargetType Class<T> targetType) {
if (obj == null) {
return null;
}
return targetType.getConstructor(objClass).newInstance(obj);
}
default <T extends Serializable, Z extends SingleValue<T>> T getValue(Z singleValue) {
if (singleValue == null) {
return null;
}
return singleValue.getValue();
}
default <T extends SingleValue<String>> T singleValue(String obj, @TargetType Class<T> targetType) {
return singleValue(obj, String.class, targetType);
}
}
Для FirstName -> другое расширение сопоставления объекта SingleValue. Я нашел следующее решение, которое не работало:
default <T extends SingleValue<String>> T stringSingleValue(SingleValue<String> obj, @TargetType Class<T> targetType)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
return singleValue(obj.getValue(), String.class, targetType);
}
Проблемы с методом отображения, упомянутым выше:
- Mapstruct предпочтет отображение getValue (Z singleValue) над этим в автоматическом выборе (я действительно не хочу использовать Qualifiers, потому что тогдаянеобходимо указать каждое поле, которое я сопоставляю)
- Mapstruct будет считать метод сопоставления неоднозначным, если мы, например, добавим его для единичных значений UUID
работает, этот вызов генерируется mapstructкогда отображение String в A расширяет SingleValue:
A a = singleValueMapper.singleValue( client.getCompanyName(), A.class )
Этот вызов не выбирается mapstruct, но мы можем использовать его, когда вручную используем его с @Mapping в качестве выражения.Однако мы бы хотели, чтобы mapstruct автоматически отображала эти вызовы, когда отображение A расширяет SingleValue до B, расширяет SingleValue:
B b =singleValueMapper.stringSingleValue(command.getTitle(), B.class)
Есть ли способ осуществить это с помощью mapstruct и java generics?
Iиспользую Mapstruct версии 1.3.0-final.