当前位置: 首页 > 知识库问答 >
问题:

推土机未正确映射集合

濮阳茂材
2023-03-14

所以,我有一个问题,这里的人可能会帮助我与推土机。

背景:我设置了Dozer来将我的持久性实体映射到它们的DTO类。这很简单,我只是创建一个实体类的精确副本作为POJO,并允许dozer通配符查看字段的名称是否与源字段匹配。我正在使用自定义映射器处理Hibernate延迟加载问题,就像这里所做的那样。我告诉Dozer如何通过一个类来映射每个类,该类扫描实体中名为@EntityMap(DTOxxx.class)的注释。然后它将其添加到映射器addMaps(构建器)中

问题:(阅读最后的研究,了解最新信息,但阅读所有这些也有助于获得上下文)问题是Dozer在某些实例中没有正确映射我的集合。例如,在我的类别实体类中,我有一个Dozer需要映射的其他实体的集合。发生的情况是dozer找到了在这种情况下有2个项目的集合,并且在新的DTO类集合中只映射了1个项目。

正如您在调用toDomain后的图像中所看到的(其中包含mapper.map(source,desination)推土机调用),DTO只有从实体映射到其中的2个对象中的1个。下面是要查看的toDomain方法encase:

@Transactional(readOnly=true)
public <T extends DomainObject> T toDomain(Class<T> clazz, Entity entity) {
    if (entity == null) {
        return null;
    }

    T domain = getCachedDomainObjects(clazz, entity.getId());
    if (domain == null) {
        domain = dozerMapper.map(entity, clazz);
        cacheDomainObject(domain);
    }
    return domain;
}

如果您这样想的话,我已经确保它不会抓取缓存的实体。

所以我有点困惑,为什么在某些情况下会发生这种情况,而在其他情况下不会发生这种情况。我看不出它起作用的场合和不起作用的场合有什么明显的区别。如果有人以前遇到过这样的问题,并且认为他们能够帮助我,那就太棒了!以下是我在本期示例中的课程:

类别实体。java:

@EntityMapping(Category.class)
@javax.persistence.Entity(name = "categories")
public class CategoryEntity implements Entity, PureTable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true, nullable = false)
    private int id = Entity.UNSAVED_ID;

    @OneToMany(mappedBy = "pk.category", fetch = FetchType.LAZY)
    @Cascade({CascadeType.SAVE_UPDATE})
    private Set<IncidentJoinCategoryEntity> incidentJoinCategories =
        new HashSet<IncidentJoinCategoryEntity>();

    @Override
    public int getId() {
        return this.id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public Set<IncidentJoinCategoryEntity> getIncidentJoinCategories() {
        return incidentJoinCategories;
    }
    public void setIncidentJoinCategories(Set<IncidentJoinCategoryEntity> 
        incidentJoinCategories) {
        this.incidentJoinCategories = incidentJoinCategories;
    }
}

这个类有一个完全匹配其值的DTO类:

类别java:

public class Category {

    int id;

    Set<IncidentJoinCategory> incidentJoinCategories= 
    new HashSet<IncidentJoinCategory>();

    @Override
    public int getId() {
        return id;
    }
    @Override
    public void setId(int id) {
        this.id = id;
    }

    public Set<IncidentJoinCategory> getIncidentJoinCategories() {
        return incidentJoinCategories;
    }
    public void setIncidentJoinCategories(Set<IncidentJoinCategory> 
        incidentJoinCategories) {
        this.incidentJoinCategories = incidentJoinCategories;
    }
}

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 研究!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

编辑#1:

可以所以我花了几个小时调试这个问题,以了解这里发生了什么。事实证明,最新来源的MappingProcessor类第749行(推土机5.4.0)或第766行中存在此问题(但我尚未检查最新来源中是否仍存在此问题,但怀疑是否已修复)。

这条线是

((Set) field).addAll(result);

它试图在这里绘制的是一个

HashSet<IncidentJoinCategoryEntity>

addAll(result)仅向((Set)字段)集合添加1项。其中有2个项目的结果(在调试期间,它也是大小2,我将提供变量的快照)仅向((Set)字段)转换添加1个值。

result  LinkedHashSet<E>  (id=220)  
    map LinkedHashMap<K,V>  (id=248)    
        accessOrder false   
        entrySet    HashMap$EntrySet  (id=251)  
        hashSeed    -1187793029 
        header  LinkedHashMap$Entry<K,V>  (id=253)  
        keySet  HashMap$KeySet  (id=5829)   
        loadFactor  0.75    
        modCount    2   
        size    2   
        table   HashMap$Entry<K,V>[16]  (id=258)    
        threshold   12  
        useAltHashing   false   
        values  null    
field   HashSet<E>  (id=221)    
    map HashMap<K,V>  (id=247)  
        entrySet    HashMap$EntrySet  (id=5856) 
        hashSeed    1372273954  
        keySet  HashMap$KeySet  (id=5821)   
        loadFactor  0.75    
        modCount    2   
        size    1   
        table   HashMap$Entry<K,V>[16]  (id=5822)   
        threshold   12  
        useAltHashing   false   
        values  null    

编辑#2:

下载源代码以进行更多调试:

if (field == null) {
  Class<? extends Set<?>> destSetType = (Class<? extends Set<?>>) fieldMap.getDestFieldType(destObj.getClass());
  return CollectionUtils.createNewSet(destSetType, result);
} else {
  System.out.println("----IN----");
  // Bug #1822421 - Clear first so we don't end up with the removed orphans again
  Set ret = (Set) field;
  ret.clear();
  //((Set) field).addAll(result);
  for(Object res : result) {
      System.out.println("FOUND " + res.toString());
      ret.add(res);
  }
  System.out.println("END SIZE " + ret.size());
  System.out.println("----OUT----");
  return ret;
}

这种情况下的输出:

----IN----
FOUND nz.co.doltech.ims.project.shared.domains.joins.IncidentJoinCategory@3e2
FOUND nz.co.doltech.ims.project.shared.domains.joins.IncidentJoinCategory@3e2
END SIZE 1
----OUT----

它的输出是2个项目,但正如您所看到的@3e2,由于某些原因,它们是相同的项目。因此,当您调用addAll时,它会删除重复项,只剩下1项。为什么推土机意外映射了相同值的2?我检查以确保源对象集合没有将相同的项目折叠起来,而且确实没有。真的很奇怪。

编辑#3:

我在这里做了进一步的测试,但运气不好。对于具有相同值的Dozer mapping 2来说,这确实是一个问题,addAll会取消重复项,使其仅成为列表中的一项。不幸的是,我无法很容易地调试addToSet中的递归方法来确定发生这种情况的原因。

会更新,如果我想出了别的什么,否则我对这个没有想法,哈哈。

共有1个答案

东门晨
2023-03-14

事实证明,这实际上不是推土机的错误。调试表明推土机是罪魁祸首,但我认为情况并非如此。我认为这是因为我换了另一个有相同问题的地图绘制程序,所以除非这个新的地图绘制程序有相同的问题(lol),否则它不是推土机。如果有人知道我为什么会这样,我会非常感谢你的帮助。

目前我猜测是hibernate自定义字段映射器,我已经准备好了它来处理延迟的负载敏感集合。我之所以忽略这一点,首先是因为当我开始调试推土机时,推土机似乎在从addToSet返回之前映射字段,所以我错误地认为它已经应用了自定义字段映射。

 类似资料:
  • 我是使用dozer的新手。我需要将集合映射到一个类,该类是集合中源类的属性。我有如下类技术 我想映射到 哪里 我的推土机绘图将是什么样子?

  • 我在srcopobject中收集了StateTax和LocalTax。这需要映射到StateLocalTax的集合。在SrcObject中,如果我有三个SrcStateTax和两个SrcLocalTax,我想将它们映射到一个StateLocalTax集合,该集合将有四个元素。此集合的三个元素将包含stateTax信息和null destLocalTaxGroup,一个元素将包含destLocalT

  • 我试图使用Dozer映射UUID字段,遇到了Dozer github上提到的一个问题: https://github.com/DozerMapper/dozer/issues/83 问题是-显然,Dozer依赖于UUID中不存在的默认无参数构造函数。因此,该链接显示了如何告知推土机执行参考复制。然而,使用该提示并没有帮助,我仍然会遇到以下异常: org.dozer.java.lang.java.u

  • 我在Spring启动时使用推土机映射器。如果我将数据从实体映射到EntityDTO,那么dozer maper的工作就是将数据从实体类复制到EntityDTO,对于原语也是如此。但是假设我有这样一门课 和名称为EntityDTO的DTO 那么它不会将数据从entityChild映射到EntityChildTos,有人能帮我解决这个问题吗?

  • 在Dozer的帮助下,我想将映射到DTO类 但是这两种设置

  • 我公开了一个使用另一个SOAP服务的服务。我得到了JAXB生成的服务模型。当我使用服务时,数据被设置到与此模型相关的对象中。我定义了自己的域模型,它与JAXB模型具有完全相同的类集,但没有xml注释等。我使用dozer来执行数据映射。当标记为注释(nillable=true)的某些布尔元素为null时,我的域模型中的目标对象布尔对象将设置为默认的true或false值。我希望它保留相同的空值。布尔