3

我正在使用Dozer框架在 Java Bean 之间进行转换。我想使用 Dozer 的 Java Api 而不是 XML 创建我的映射,以便能够操作和配置我的自定义转换器。

如果我在下面的代码中使用替代 1 运行我的转换器,并删除了 alt 2 - xml 文件中的映射,则转换工作正常并且我的自定义转换器被调用。如果我使用备选方案 2 运行转换器 - 使用 java API 进行映射,则映射器永远不会调用我的转换器。bean被转换,但是同类型的嵌套字段被忽略,在下面的代码中,父字段转换后为null。

Organization org = ...init organization....
OrganizationDto orgDto = new MyConverter().convert(organization, OrganizationDto.class);
assertEquals(3,orgDto.getParent().getX()) //Fails due to NPE since parent field is not copied

我知道 java API 不支持类级别的自定义转换器,但是字段级别的转换器看起来像是受支持的,因为它是在 java 映射 API示例中提供的。

(我也知道推土机作者建议将推土机用作单例,但这不包括在下面的示例中。)

有什么提示吗?

public class OrganizationDto {
   int x;
   OrganizationDto parent ;
   // getters and setters....
}

public class Organization {
   int x;
   Organization parent ;
   // getters and setters....
}


public class MyConverter{


private DozerBeanMapper mapper = null;

public MyConverter() {
        mapper = new DozerBeanMapper();
        // Alternative 1 - works 
//          List<String> myMappingFiles = new ArrayList<String>();
//          myMappingFiles.add("myBeanMappings.xml");
//          mapper.setMappingFiles(myMappingFiles);

        // Alternative 2 - does not work
        Map<String,CustomConverter> customConvertersWithId = new HashMap<String, CustomConverter>();
        customConvertersWithId.put("OrganizationDetailsConverter", new OrganizationDetailsConverter());
        mapper.setCustomConvertersWithId(customConvertersWithId);

        // Also tried variants using
        //mapper.setCustomConverters(Collections.<CustomConverter> singletonList(new OrganizationDetailsConverter()));

        BeanMappingBuilder builder = new BeanMappingBuilder() {
            protected void configure() {
                mapping(OrganizationDto.class, Organization.class)
                .fields("parent",
                        "parent",
                        customConverterId("OrganizationDetailsConverter"));
                }
            };          
            mapper.addMapping(builder);
    }

    public <T, S> T convert(S fromBean, Class<T> toBeanClass) {
    return mapper.map(fromBean, toBeanClass);
    }

}



<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://dozer.sourceforge.net
      http://dozer.sourceforge.net/schema/beanmapping.xsd">
    <mapping>
        <class-a>foo.OrganizationDto</class-a>
        <class-b>foo.Organization</class-b>
        <field custom-converter="foo.OrganizationDetailsConverter">
            <a>parent</a>
            <b>parent</b>
        </field>
    </mapping>
</mappings>
4

1 回答 1

1
public class DozerMap {

   public static class ContainerA {
      private A a;
      public A getA() { return a; }
      public void setA(A a) { this.a = a; }
   }

   public static class ContainerB {
      private B b;
      public B getB() { return b; }
      public void setB(B b) { this.b = b; }
   }

   private static class A { };

   private static class B { };

   static class ConverterImpl extends DozerConverter<A, B> {

      ConverterImpl() {
         super(A.class, B.class);
      }

      @Override
      public B convertTo(A source, B destination) {
         Logger.getAnonymousLogger().info("Invoked");
         return destination;
      }

      @Override
      public A convertFrom(B source, A destination) {
         Logger.getAnonymousLogger().info("Invoked");
         return destination;
      }
   }

   public static void main(String[] args) {

      DozerBeanMapper mapper = new DozerBeanMapper();
      mapper.setCustomConverters(Collections.<CustomConverter> singletonList(new ConverterImpl()));
      BeanMappingBuilder foo = new BeanMappingBuilder() {

         @Override
         protected void configure() {
            mapping(ContainerA.class, ContainerB.class).fields("a", "b", FieldsMappingOptions.customConverter(ConverterImpl.class));
         }
      };
      mapper.setMappings(Collections.singletonList(foo));
      ContainerA containerA = new ContainerA();
      containerA.a = new A();
      ContainerB containerB = mapper.map(containerA, ContainerB.class);
   }
}
于 2015-01-14T17:09:09.877 回答