Как отобразить элементы JAXB, аннотированные @XMLSeeAlso, используя mapStruct?

Я пытаюсь отобразить bean-компонент, который имеет некоторые элементы JAXB, такие как @XmlSeeAlso, @XmlElement, @XmlSchemaType, в качестве свойств для этого класса.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Customer")
@XmlSeeAlso({PersonalCustomer.class, BusinessCustomer.class})
public class Customer extends Role {

 @XmlElement(name = "AMLLineOfBusiness")
private LOB amlLineOfBusiness;
 // 50 odd properties
 //some properties with XmlElement/XmlSchemaType 
 // getters and setters   
}

@Mapper
public interface CustomerMapper {
     PersonalCustomer personcalCustomerToPersonalCustomer(PersonalCustomer pc);
@Mappings({
    /*Several other ignore mappings*/
    @Mapping(target="AMLLineOfBusiness",ignore=true)
    })
     Customer customerToCustomer(Customer customer);
   }

Теперь я сталкиваюсь с проблемами ниже при отображении с использованием mapStruct.

  1. Бин PersonalCustomer не отображается. Я не вижу этого в ответе. Но он отлично работает при использовании бульдозера. Все, что мне нужно сделать, это определить его в сопоставлении в конфигурации Dozer XML. Я пробовал аналогичную вещь в mapStruct. Я определил personcalCustomerToPersonalCustomermethod в интерфейсе Mapper с необходимыми сопоставлениями и игнорируя необязательные поля. Хотя в mapperImpl есть реализация, но я не вижу, чтобы она использовалась где-либо в классе impl.

  2. Игнорируя поля, которые имеют @XmlElement или @XmlSchemaType, я получаю ошибку компиляции при генерации кода impl. Ниже приведена ошибка трассировки статка. Я получил ошибку компиляции, когда я использовал amlLineOfBusiness.

    [70,2] ошибка: неизвестное свойство "amlLineOfBusiness" в типе результата com.role.Customer. Вы имели в виду "lineOfBusiness"? [ОШИБКА] -> [Справка 1] org.apache.maven.lifecycle.LifecycleExecutionException: не удалось выполнить цель org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) в службе проекта -jar: ошибка компиляции C:\Perforce\service-jar\2018.08.0\service-jar\src\main\java\com\mapstruct\mapper\CustomerMapper.java:[70,2] ошибка: неизвестное свойство "amlLineOfBusiness" в результате введите com.role.Customer. Вы имели в виду "lineOfBusiness"? в org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212) в org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) в org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) в org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:108) в org.apache.maven.lifecycle.internal.adedderilult $1.call(MultiThreadedBuilder.java:188) в org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:184) в java.util.concurrent.FutureTask.rk.java Future:266) в java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) в java.util.concurrent.FutureTask.run(FutureTask.java:266) в java.util.concurrent.ThreadPoolExorker.un ThreadPoolExecutor.java:1149) в java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) в java.lang.Thread.run(Thread.java:748) C предоставлено: org.apache.maven.plugin.compiler.CompilationFailureException: ошибка компиляции

    Вышеуказанное разрешается, когда я использовал игнорируемое значение имени (@XmlElement(name="AMLLineOfBusiness")). Я не мог понять, что именно здесь происходит.

  3. По умолчанию mapStruct также отображает поля суперкласса. В моем случае класс Customer также получает свойства Role. Нет другого выбора, кроме как использовать ignore=true для каждого свойства. Это довольно беспокойно, так как у меня есть 50 нечетных полей и десятки похожих карт в зависимости от требований сервиса. Я бы хотел, чтобы mapStruct имел функцию игнорирования всех полей по умолчанию или стратегию для отображения только указанных полей.

Обратите внимание, что оба типа источника и назначения здесь одинаковы. Мне нужно только сопоставить определенные поля в зависимости от требования. Я застрял здесь. Я высоко ценю вашу помощь.

1 ответ

Решение

Кажется, у вас есть 3 разные проблемы.

  1. Кажется, что вы пытаетесь достичь, чтобы MapStruct обнаружил все возможные реализации для Customer (или посмотреть @XmlSeeAlso) и используйте метод, который вам нужен. Это невозможно автоматически в MapStruct. Смотрите #131 для запроса существующей функции.
  2. Это должно произойти, если вы не определили свойство правильно. MapStruct фактически просматривает только геттеры и сеттеры (не в поле). Так что, если вы получите getAM тогда ваш @Mapping(target = "AMLLineOfBusiness", ignore = true)
  3. Это похоже на этот вопрос. Может быть, вы можете попробовать повторно использовать конфигурации сопоставления

Возможное решение для 1 было бы вы на экземпляр на вашей стороне.

@Mapper
public interface CustomerMapper {
    PersonalCustomer personcalCustomerToPersonalCustomer(PersonalCustomer pc);

    default Customer customerToCustomer(Customer customer) {
        if (customer instanceOf PersonalCustomer) {
            return personalCustomerToPersonalCustomer((PersonalCustomer) pc);
        } else if (customer instanceOf BusinessCustomer) {
            return businessCustomerToBusinessCustomer((BusinessCustomer) pc);
        }
    }
}

Причина этого заключается в том, что MapStruct является процессором аннотаций, поэтому он генерирует код во время компиляции. С другой стороны, Dozer работает с информацией о времени выполнения. Dozer может получить класс во время выполнения и выбрать правильный метод. MapStruct не может вывести все возможные реализации.

Другие вопросы по тегам