Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 推土机双向映射(字符串,字符串)与自定义转换器不可能?_Java_Mapping_Dozer - Fatal编程技术网

Java 推土机双向映射(字符串,字符串)与自定义转换器不可能?

Java 推土机双向映射(字符串,字符串)与自定义转换器不可能?,java,mapping,dozer,Java,Mapping,Dozer,我有一个带有自定义转换器的推土机映射: <mapping> <class-a>com.xyz.Customer</class-a> <class-b>com.xyz.CustomerDAO</class-b> <field custom-converter="com.xyz.DozerEmptyString2NullConverter"> <a>customerName&l

我有一个带有自定义转换器的推土机映射:

<mapping>
    <class-a>com.xyz.Customer</class-a>
    <class-b>com.xyz.CustomerDAO</class-b>
    <field custom-converter="com.xyz.DozerEmptyString2NullConverter">
        <a>customerName</a>
        <b>customerName</b>
    </field>
</mapping>
public class DozerEmptyString2NullConverter extends DozerConverter<String, String> {

    public DozerEmptyString2NullConverter() {
        super(String.class, String.class);
    }

    public String convertFrom(String source, String destination) {
        String ret = null;
        if (source != null) {
            if (!source.equals(""))
            {
                ret = StringFormatter.wildcard(source);
            } 
        }
        return ret;
    }

    public String convertTo(String source, String destination) {
        return source;
    }
}

com.xyz.Customer
com.xyz.CustomerDAO
客户名称
客户名称
和转换器:

<mapping>
    <class-a>com.xyz.Customer</class-a>
    <class-b>com.xyz.CustomerDAO</class-b>
    <field custom-converter="com.xyz.DozerEmptyString2NullConverter">
        <a>customerName</a>
        <b>customerName</b>
    </field>
</mapping>
public class DozerEmptyString2NullConverter extends DozerConverter<String, String> {

    public DozerEmptyString2NullConverter() {
        super(String.class, String.class);
    }

    public String convertFrom(String source, String destination) {
        String ret = null;
        if (source != null) {
            if (!source.equals(""))
            {
                ret = StringFormatter.wildcard(source);
            } 
        }
        return ret;
    }

    public String convertTo(String source, String destination) {
        return source;
    }
}
公共类DozerEmptyString2NullConverter扩展了DozerConverter{
公共DozerEmptyString2NullConverter(){
super(String.class,String.class);
}
公共字符串转换源(字符串源、字符串目标){
字符串ret=null;
如果(源!=null){
如果(!source.equals(“”)
{
ret=StringFormatter.wildcard(源);
} 
}
返回ret;
}
公共字符串转换器(字符串源、字符串目标){
返回源;
}
}
当我在一个方向(Customer->CustomerDAO)调用映射器时,将调用方法“convertTo”

由于Dozer能够处理双向映射,我希望,只要我在相反方向调用映射器,就会调用方法“convertFrom”

但是从不调用convertTo方法

我怀疑问题在于,这两种类型都是字符串-但我如何才能使其工作


作为一种解决方法,我创建了双向映射,这是标准解决方案还是行为是一个bug?

是的,问题是源类和目标类是相同的。这是用于推土铲转换器的推土铲:

  public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) {
    Class<?> wrappedDestinationClass = ClassUtils.primitiveToWrapper(destinationClass);
    Class<?> wrappedSourceClass = ClassUtils.primitiveToWrapper(sourceClass);

    if (prototypeA.equals(wrappedDestinationClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeB.equals(wrappedDestinationClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeA.equals(wrappedSourceClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeB.equals(wrappedSourceClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeA.isAssignableFrom(wrappedDestinationClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeB.isAssignableFrom(wrappedDestinationClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeA.isAssignableFrom(wrappedSourceClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeB.isAssignableFrom(wrappedSourceClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else {
      throw new MappingException("Destination Type (" + wrappedDestinationClass.getName()
          + ") is not accepted by this Custom Converter (" 
          + this.getClass().getName() + ")!");
    }

  }
public class DirectionAwareDozerBeanMapper extends DozerBeanMapper implements DirectionAware {
    private Direction direction;

    public DirectionAwareDozerBeanMapper(Direction direction) {
        super();
        this.direction = direction;
    }

    public DirectionAwareDozerBeanMapper(Direction direction, List<String> mappingFiles) {
        super(mappingFiles);
        this.direction = direction;
    }

    @Override
    protected Mapper getMappingProcessor() {
        try {
            Method m = DozerBeanMapper.class.getDeclaredMethod("initMappings");
            m.setAccessible(true);
            m.invoke(this);
        } catch (NoSuchMethodException|SecurityException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) {
            // Handle the exception as you want
        }

        ClassMappings arg1 = (ClassMappings)getField("customMappings");
        Configuration arg2 = (Configuration)getFieldValue("globalConfiguration");
        CacheManager arg3 = (CacheManager)getField("cacheManager");
        StatisticsManager arg4 = (StatisticsManager)getField("statsMgr");
        List<CustomConverter> arg5 = (List<CustomConverter>)getField("customConverters");
        DozerEventManager arg6 = (DozerEventManager)getField("eventManager");
        Map<String, CustomConverter> arg7 = (Map<String, CustomConverter>)getField("customConvertersWithId");

        Mapper mapper = new DirectionAwareMappingProcessor(arg1, arg2, arg3, arg4, arg5,
                                arg6, getCustomFieldMapper(), arg7, direction);

        return mapper;
    }

    private Object getField(String fieldName) {
        try {
            Field field = DozerBeanMapper.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(this);
        } catch (NoSuchFieldException|SecurityException|IllegalArgumentException|IllegalAccessException e) {
            // Handle the exception as you want
        }
        return null;
    }

    public Direction getDirection() {
        return direction;
    }
}
公共对象转换(对象existingDestinationFieldValue、对象sourceFieldValue、类destinationClass、类sourceClass){
Class wrappedDestinationClass=ClassUtils.PrimitiveToRapper(destinationClass);
Class wrappedSourceClass=ClassUtils.primitiveToRapper(sourceClass);
if(原型a.equals(wrappedDestinationClass)){
返回convertFrom((B)sourceFieldValue,(A)existingDestinationFieldValue);
}else if(原型B.equals(wrappedDestinationClass)){
返回convertTo((A)sourceFieldValue,(B)existingDestinationFieldValue);
}else if(原型a.equals(wrappedSourceClass)){
返回convertTo((A)sourceFieldValue,(B)existingDestinationFieldValue);
}else if(原型B.equals(wrappedSourceClass)){
返回convertFrom((B)sourceFieldValue,(A)existingDestinationFieldValue);
}else if(原型a.isAssignableFrom(wrappedDestinationClass)){
返回convertFrom((B)sourceFieldValue,(A)existingDestinationFieldValue);
}else if(原型B.isAssignableFrom(wrappedDestinationClass)){
返回convertTo((A)sourceFieldValue,(B)existingDestinationFieldValue);
}else if(原型a.isAssignableFrom(wrappedSourceClass)){
返回convertTo((A)sourceFieldValue,(B)existingDestinationFieldValue);
}else if(原型B.isAssignableFrom(wrappedSourceClass)){
返回convertFrom((B)sourceFieldValue,(A)existingDestinationFieldValue);
}否则{
抛出新的MappingException(“目标类型”(+wrappedDestinationClass.getName()
+“”不被此自定义转换器接受(“”)
+这个.getClass().getName()+”);
}
}

不要使用
convertFrom
convertTo
方法(这是新API的一部分),而是按照您必须实现的
CustomConverter.convert
中所示的原始方法进行。我遇到了相同的问题,目前(从Dozer 5.5.x开始)没有简单的方法,但有复杂的方法

注意,它依赖于JVM中没有启用安全管理器,否则您将需要在安全规则中添加一些权限。这是因为该解决方案使用反射来访问Dozer类的私有字段

您需要扩展两个类:
DozerBeanMapper
MappingProcessor
。您还需要方向和接口的枚举来从上述类获取方向

枚举:

public enum Direction {
    TO,
    FROM;
}
界面:

public interface DirectionAware {
    Direction getDirection();
}
扩展DozerBeanMapper的类:

  public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) {
    Class<?> wrappedDestinationClass = ClassUtils.primitiveToWrapper(destinationClass);
    Class<?> wrappedSourceClass = ClassUtils.primitiveToWrapper(sourceClass);

    if (prototypeA.equals(wrappedDestinationClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeB.equals(wrappedDestinationClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeA.equals(wrappedSourceClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeB.equals(wrappedSourceClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeA.isAssignableFrom(wrappedDestinationClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else if (prototypeB.isAssignableFrom(wrappedDestinationClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeA.isAssignableFrom(wrappedSourceClass)) {
      return convertTo((A) sourceFieldValue, (B) existingDestinationFieldValue);
    } else if (prototypeB.isAssignableFrom(wrappedSourceClass)) {
      return convertFrom((B) sourceFieldValue, (A) existingDestinationFieldValue);
    } else {
      throw new MappingException("Destination Type (" + wrappedDestinationClass.getName()
          + ") is not accepted by this Custom Converter (" 
          + this.getClass().getName() + ")!");
    }

  }
public class DirectionAwareDozerBeanMapper extends DozerBeanMapper implements DirectionAware {
    private Direction direction;

    public DirectionAwareDozerBeanMapper(Direction direction) {
        super();
        this.direction = direction;
    }

    public DirectionAwareDozerBeanMapper(Direction direction, List<String> mappingFiles) {
        super(mappingFiles);
        this.direction = direction;
    }

    @Override
    protected Mapper getMappingProcessor() {
        try {
            Method m = DozerBeanMapper.class.getDeclaredMethod("initMappings");
            m.setAccessible(true);
            m.invoke(this);
        } catch (NoSuchMethodException|SecurityException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) {
            // Handle the exception as you want
        }

        ClassMappings arg1 = (ClassMappings)getField("customMappings");
        Configuration arg2 = (Configuration)getFieldValue("globalConfiguration");
        CacheManager arg3 = (CacheManager)getField("cacheManager");
        StatisticsManager arg4 = (StatisticsManager)getField("statsMgr");
        List<CustomConverter> arg5 = (List<CustomConverter>)getField("customConverters");
        DozerEventManager arg6 = (DozerEventManager)getField("eventManager");
        Map<String, CustomConverter> arg7 = (Map<String, CustomConverter>)getField("customConvertersWithId");

        Mapper mapper = new DirectionAwareMappingProcessor(arg1, arg2, arg3, arg4, arg5,
                                arg6, getCustomFieldMapper(), arg7, direction);

        return mapper;
    }

    private Object getField(String fieldName) {
        try {
            Field field = DozerBeanMapper.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(this);
        } catch (NoSuchFieldException|SecurityException|IllegalArgumentException|IllegalAccessException e) {
            // Handle the exception as you want
        }
        return null;
    }

    public Direction getDirection() {
        return direction;
    }
}
现在是用法

1) 每当您想要映射相同的基本类型(例如字符串)时,请在dozer映射文件中将该类型用作两个参数的自定义转换器。这种转换器的实现应该扩展:
DozerConverter
并实现
MapperAware
接口。这一点很重要,您必须有可用的
MapperAware
,因为有了mapper,您将能够将其投射到
DirectionAware
,然后获得方向

例如:

public class MyMapper extends DozerConverter<String, String> implements MapperAware {
    private DirectionAware dirAware;

    public MyMapper(Class<String> cls) {
        super(cls, cls);
    }

    @Override
    public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<String> destinationClass, Class<String> sourceClass) {
        if (dirAware.getDirection() == Direction.FROM) {
            // TODO convert sourceFieldValue for "FROM" direction and return it
        } else {
            // TODO convert sourceFieldValue for "TO" direction and return it
        }
    }

    @Override
    public void setMapper(Mapper mapper) {
        dirAware = (DirectionAware)mapper;
    }
}
DirectionAwareDozerBeanMapper mapperFrom = DirectionAwareDozerBeanMapper(mappingFiles, Direction.FROM);
DirectionAwareDozerBeanMapper mapperTo = DirectionAwareDozerBeanMapper(mappingFiles, Direction.TO);

当然,您需要使用适当的映射器(from/to)向自定义映射器提供有关您映射的方向的信息。

几年后,我遇到了类似的问题,不知何故,DozerConverter API作为一种新的API,仍然不能作为双向正确工作

因此,我没有讨论这里建议的所有这些复杂的解决方案,而是创建了两个单向映射来解决这个问题(使用)。然后我的转换开始起作用。我使用的DozerConverter api如下所示:


公共类MapToStringConverter扩展了DozerConverter

我对新API也有同样的问题。我不知道映射程序是调用convertTo()还是convertFrom()。旧的api也不起作用,因为我仍然无法区分映射的工作方向。我要从一根绳子转到另一根绳子。简单的映射,我需要将数据库代码映射到用户可读的值。如果有人对此有所了解,将非常感谢反馈。谢谢