【问题标题】:Dozer problems with maps generic types and proxies映射泛型类型和代理的推土机问题
【发布时间】:2015-10-10 13:12:44
【问题描述】:

在我们公司,我们发现 Dozer 在将字段从休眠实体复制到带有字段的简单 DTO(简单 POJO)时存在问题,这些字段是其他实体的映射。 看起来是这样的:

class MyJPAEntity{
     @JPAMappings(FetchType.EAGER)
     Map<Integer, EmbeddableJPAEntity> map;
}

class MyDto{
    Map<Integer, MyOtherDto> map;
}

推土机 Soo 在尝试将字段从实体复制到 DTO 时尝试以某种方式复制代理而不是其内容,从而引发 LazyInitializationException(即使 Fetch 类型为 EAGER)。我们发现,我们可以创建一个包装器和一个自定义转换器来处理这种情况:

public class MaybePersistentMapToHashMapConverter extends
    DozerConverter<Map, Map> implements MapperAware {

    public static class Wrapper {
        private Map map;

        public Wrapper() {
        }

        public Wrapper(Map map) {
            this.map = map;
        }

        public Map getMap() {
            return map;
        }

        public void setMap(Map map) {
            this.map = map;
        }
    }

    private Mapper mapper;

    public MaybePersistentMapToHashMapConverter() {
        super(Map.class, Map.class);
    }

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

    @Override
    public Map convertTo(Map source, Map destination) {
        return map(source, destination);
    }

    @Override
    public Map convertFrom(Map source, Map destination) {
        return map(source, destination);
    }

    private Map map(Map source, Map destination) {
        Wrapper wrapper;

        if (source instanceof PersistentMap) {
            wrapper = new Wrapper(new HashMap<>(source));
        } else {
            wrapper = new Wrapper(source);
        }

        if (destination == null) {
            Wrapper map = mapper.map(wrapper, Wrapper.class);
            return map.map;
        } else {
            throw new UnsupportedOperationException();
        }
    }
}

所以这玩意,只是把地图包裹起来,这样推土机就不会复制proxyMap了。我只是在代码中配置了一个映射:

mapping(fromType, toType, oneWay())
            .fields("map", "map",  FieldsMappingOptions.customConverter(MaybePersistentMapToHashMapConverter.class)

到目前为止一切顺利。 那么问题出在哪里? 问题在于另一种映射方式——从 DTO 到实体。而不是从 MyDto 复制到 MyJPAEntity 条目到实体(通过将内部 DTO 映射到内部实体,它实际上将带有条目的映射复制到 MyJPAEntity 中 - 可能它无法猜测目标类型是什么,而不是映射对象,它只是复制它们。

所以我也能够通过指定地图类型的提示来解决问题:

fields("map", "map", FieldsMappingOptions.hintA(MyOtherDto.class), FieldsMappingOptions.hintB(EmbeddableJPAEntity.class) )

我可能已经帮助了一些人;)并且很高兴我解决了我的问题。

直到我不得不使用 doser 将值从一个实体复制到另一个实体。现在,如果我使用提示,我会得到 LazyInitException,如果我使用上面的包装转换器,则映射器会忽略提示。 Dozer 的 sourceforge 文档现在无法访问。 有谁知道如何使用映射器并强制它使用我的提示?或者如何通过映射构建器正确配置它?

我想说的是,MaybePersistentMapToHashMapConverter 中使用的映射器实际上并不知道它应该使用提示,因为它不知道它实际上正在映射一个名为“map”的字段

【问题讨论】:

    标签: java hibernate dictionary proxy dozer


    【解决方案1】:

    在我们的项目中,我们解决了这个问题并严重陷入了与您解决的问题完全相同的问题;)。

    您的 LazyInitializationException 可能是用于在推土机的 map 方法中调用 .class。 那是因为推土机将实例化新实体并​​填充它,并且该实体不在当前会话中。 我们改变我们的推土机地图方法调用:

    A_Entity newEntity = dozer.map(dto,A_Entity.class);
    

    到:

    A_Entity newEntity = new A_Entity();
    dozer.map(A_dto,newEntity);
    

    还有其他方式:

    A_dto dto = dozer.map(entity,A_DTO.class);
    

    到:

    A_dto dto = Spring.context.getBean("a_dto");
    dozer.map(entity,dto);
    

    我希望这会有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      相关资源
      最近更新 更多