使用 Dozer 的自定义转换器将对象列表映射到另一个列表

Map a list of object to another list using Dozer's custom converters

我想做的是使用 Dozer 将实体列表映射到它们的字符串 ID 列表(或多或少)。

很明显,它暗示了Custom Converter。我的第一个想法是制作一个从 MyEntity 到 String 的转换器,然后对 Dozer 说 "Map every object of this collection using this converter"。但是我不知道该怎么做。

所以我的第二个想法是让转换器直接将实体列表转换为字符串列表。我对这个想法的问题是,我正在努力做一些荒谬的事情,即在构造函数中获取列表的类型,如下所示(根本不起作用):

public MyEntityListConverter() {
    super(List<MyEntity>.class, List<String>.class);
}

我不知道如何在不声明任何内容的情况下在单行中传递实例化列表的 class。

所以如果有人知道:

由于泛型类型,您尝试的方法无法实现。如果是,Dozer 无法在运行时检测类型。

第一个解决方案List<>

您的转换器:

public class MyEntityToStringConverter extends DozerConverter<MyEntity, String> {
    // TODO constructor + impl
}

您的映射:

mapping(MyEntityA.class, MyEntityB.class)
.fields("myEntityList", "myStringList",
    hintA(MyEntity.class),
    hintB(String.class));

mapping(MyEntity.class, String.class)
.fields(this_(), this_(), customConverter(MyEntityToStringConverter.class));

第二个解决方案 带有列表包装器

您可以尝试创建自定义 类 扩展列表实现。

public class MyEntityList extends ArrayList<MyEntity> {

}

public class MyStringList extends ArrayList<String> {

}

更改您要映射的父 类 中的字段。

您的转换器:

public class MyEntityToStringConverter extends DozerConverter<MyEntityList, MyStringList> {
    // TODO constructor + impl
}

您的映射:

mapping(MyEntityA.class, MyEntityB.class)
.fields("myEntityList", "myStringList", customConverter(MyEntityToStringConverter.class));

另一种选择是

super((Class<List<MyEntity>>) (Class<?>) List.class,(Class<List<String>>) (Class<?>) List.class);

我非常倾向于@Ludovic 解决方案,但可能存在我的 中提到的问题。

但对我来说,稍微调整一下就可以了——在 "configuration" 中注册自定义转换器,而不是在字段级别。我正在使用 XML 配置,但它应该与编码配置一起使用:

<configuration>
  <custom-converters>
    <converter type="f.q.c.n.MyEntityToStringConverter">
      <class-a>java.lang.String</class-a>
      <class-b>f.q.c.n.MyEntity</class-b>
    </converter>
  </custom-converters>
</configuration>