繁体   English   中英

推土机映射/更新集合

[英]Dozer mapping/updating a collection

我试图将A-DTO对象映射到A-DO对象,每个对象分别具有T-DTO和T-DO的集合(列表)。 我正在尝试在REST API的上下文中进行操作。 这是否是正确的方法是一个单独的问题-我要解决的问题是更新情况。 基本上,如果A-DTO中的一个T-DTO发生更改,我希望将该更改映射到A-DO内的相应T-DO中。

我在推土机文档中找到了relationship-type="non-cumulative" ,这样就可以更新集合中的对象(如果存在)。 但是我最终将推土机插入一个新的T-DO到A-DO的收藏中!

注意:我确实实现了equals 目前仅基于主键。

有任何想法吗?

PS:而且,如果您认为处理对一对多依赖实体的更新不是一个好主意,请随时指出。.我不是100%肯定我喜欢这种方法,但是我的REST foo是不是很强。

UPDATE

equals实现:

@Override
public boolean equals(Object obj) {
    if (obj instanceof MyDOClass) {
        MyDOClass other = (MyDOClass) obj;
        return other.getId().equals(this.getId());
    }
    return false;
}

我只是遇到了同样的问题,并且解决了:

推土机使用contains来确定成员是否在集合内。
您应该实现hashCode以使"contains"能够正常工作。

您可以在以下文档页面中看到此信息: http : //dozer.sourceforge.net/documentation/collectionandarraymapping.html在“ 累积与非累积列表映射(双向) ”下:

祝好运!

最终做了一个自定义映射。

我确实做了自己的AbstractConverter,请在下面找到它:它有一些适合我的约束(可能不适合您)。

  • 将根据“ sameId”实现进行更新
  • 将会删除孤儿(目的地中的元素不在源中)。
  • 仅适用于列表(足够满足我的需求)。
  • 虽然转换器将决定更新对象的映射的决定,但是将对象的映射委派回Dozer,因此您无需实现列表中元素的映射

样品使用

public class MyConverter extends AbstractListConverter<ClassX,ClassY>{
   public MyConverter(){ super(ClassX.class, ClassY.class);}
   @Override
   protected boolean sameId(ClassX o1, ClassY o2) {
        return // your custom comparison here... true means the o2 and o1 can update each other.
   }
}

在mapper.xml中声明

<mapping>
        <class-a>x.y.z.AClass</class-a>
        <class-b>a.b.c.AnotherClass</class-b>
        <field custom-converter="g.e.MyConverter">
            <a>ListField</a>
            <b>OtherListField</b>
        </field>
    </mapping>
public abstract class AbstractListConverter<A, B> implements MapperAware, CustomConverter {

    private Mapper mapper;
    private Class<A> prototypeA;
    private Class<B> prototypeB;

    @Override
    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }

    AbstractListConverter(Class<A> prototypeA, Class<B> prototypeB) {
        this.prototypeA = prototypeA;
        this.prototypeB = prototypeB;
    }

    @Override
    public Object convert(Object destination, Object source, Class<?> destinationClass, Class<?> sourceClass) {
        if (destinationClass == null || sourceClass == null || source == null) {
            return null;
        }
        if (List.class.isAssignableFrom(sourceClass) && List.class.isAssignableFrom(destinationClass)) {
            if (destination == null || ((List) destination).size() == 0) {
                return produceNewList((List) source, destinationClass);
            }
            return mergeList((List) source, (List) destination, destinationClass);
        }
        throw new Error("This specific mapper is only to be used when both source and destination are of type java.util.List");
    }

    private boolean same(Object o1, Object o2) {
        if (prototypeA.isAssignableFrom(o1.getClass()) && prototypeB.isAssignableFrom(o2.getClass())) {
            return sameId((A) o1, (B) o2);
        }
        if (prototypeB.isAssignableFrom(o1.getClass()) && prototypeA.isAssignableFrom(o2.getClass())) {
            return sameId((A) o2, (B) o1);
        }
        return false;
    }

    abstract protected boolean sameId(A o, B t);

    private List mergeList(List source, List destination, Class<?> destinationClass) {
        return (List)
                source.stream().map(from -> {
                            Optional to = destination.stream().filter(search -> same(from, search)).findFirst();
                            if (to.isPresent()) {
                                Object ret = to.get();
                                mapper.map(from, ret);
                                return ret;
                            } else {
                                return create(from);
                            }
                        }
                ).collect(Collectors.toList());

    }

    private List produceNewList(List source, Class<?> destinationClass) {
        if (source.size() == 0) return source;
        return (List) source.stream().map(o -> create(o)).collect(Collectors.toList());
    }

    private Object create(Object o) {
        if (prototypeA.isAssignableFrom(o.getClass())) {
            return mapper.map(o, prototypeB);
        }
        if (prototypeB.isAssignableFrom(o.getClass())) {
            return mapper.map(o, prototypeA);
        }
        return null;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM