如何使用 mapStruct 映射用 @XMLSeeAlso 注释的 JAXB 元素?

How to map JAXB elements annotated with @XMLSeeAlso using mapStruct?

我正在尝试映射一个具有一些 JAXB 元素(如 @XmlSeeAlso、@XmlElement、@XmlSchemaType)的 bean 作为该 class 的属性。

@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. 未映射 bean PersonalCustomer。我没有在 回复。但它在使用推土机时效果很好。我需要做的就是 在 dozer config xml 的映射中定义它。我试过类似的东西 地图结构。我在映射器中定义了 personcalCustomerToPersonalCustomermethod 与必需的映射接口并忽略不需要的字段。虽然 实现在 mapperImpl 中,但我没有看到它被使用 impl class.

  2. 中的任意位置
  3. 同时忽略具有@XmlElement 或@XmlSchemaType 的字段, 生成 impl 代码时出现编译错误。下面是错误 统计跟踪。我在使用 amlLineOfBusiness 时出现编译错误。

    [70,2] 错误:结果类型 com.role.Customer 未知 属性 "amlLineOfBusiness"。您是说 "lineOfBusiness" 吗? [错误] -> [帮助 1] org.apache.maven.lifecycle.LifecycleExecutionException: 无法执行目标 org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) 项目服务-jar:编译失败 C:\Perforce\service-jar18.08.0\service-jar\src\main\java\com\mapstruct\mapper\CustomerMapper.java:[70,2] 错误:结果类型 com.role.Customer 未知 属性 "amlLineOfBusiness"。您是说 "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.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:188) 在 org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:184) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 java.lang.Thread.run(Thread.java:748) 原因:org.apache.maven.plugin.compiler.CompilationFailureException:编译失败

    以上是我用name值时解决的 (@XmlElement(name="AMLLineOfBusiness")) 要忽略的注释。我不能 了解这里到底发生了什么。

  4. 默认情况下 mapStruct 也映射 super class 的字段。就我而言, 客户 class 也正在获取角色的属性。别无选择 除了在每个 属性 上使用 ignore=true。这有点像我一样忙碌 有 50 个奇数字段和数十个基于服务的类似映射器 要求。我希望 mapStruct 具有默认忽略所有字段的功能,或者 仅映射指定字段的策略。

请注意,此处源类型和目标类型相同。我只需要根据需要映射某些字段。我被困在这里了。我非常感谢你的帮助。

您似乎遇到了 3 个不同的问题。

  1. 看来您要实现的目标是让 MapStruct 检测 Customer(或参见 @XmlSeeAlso)的所有可能实现并使用您需要的方法。这在 MapStruct 中是不可能自动实现的。有关现有功能请求,请参阅 #131
  2. 如果您没有正确定义 属性,就会发生这种情况。 MapStruct 实际上只查看 getters 和设置器(不在现场)。所以如果你 getter 是 getAM 那么你的 @Mapping(target = "AMLLineOfBusiness", ignore = true)
  3. 这与 question. Maybe you can try Reusing mapping configurations
  4. 类似

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 可以在运行时获取 class 并选择正确的方法。 MapStruct 无法推导出所有可能的实现。