【问题标题】:Hibernate @OneToMany association creates duplicates when saving parent entityHibernate @OneToMany 关联在保存父实体时创建重复项
【发布时间】:2014-04-23 20:32:09
【问题描述】:

我有一个涉及品牌(针对动物)的关联,然后是可以应用该品牌的动物物种。在我们的例子中,有 Brand 模型、Species 模型和关系模型 BrandSpecies。与我的问题相关的两个是 Brand 模型和 BrandSpecies 模型。

表单将发送可能已经与品牌相关联的物种的 ID。我希望避免遍历集合并检查该物种是否已被计算在内。

我尝试在一组物种上调用 clear() 并添加从服务器发送的每个 ID,但是一旦对象被持久化,旧的数据库记录仍然存在。

我的品牌关联:

public class PendingBrandModel implements Serializable, Comparable<PendingBrandModel> {
    .
    .
    .
 @JsonBackReference
 @OneToMany(mappedBy="pending_brand", cascade = {CascadeType.ALL})
 private Set<PendingBrandSpeciesModel> selected_species;

    ...
}

品牌-物种协会:

public class PendingBrandSpeciesModel implements Serializable {
...
@JsonManagedReference
@ManyToOne()
@JoinColumn(name="pending_brand", referencedColumnName="id", nullable = false)
private PendingBrandModel pending_brand;

@JsonManagedReference
@ManyToOne()
@JoinColumn(name="species", referencedColumnName="id", nullable = false)
private BrandSpeciesModel species;
// below here are the hashCode and equals override methods...
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

/* (non-Javadoc)
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    PendingBrandSpeciesModel other = (PendingBrandSpeciesModel) obj;
    Boolean brandIDsMatch = false;
    Boolean speciesIDsMatch = false;
    if(pending_brand != null && other.getPending_brand() != null) {
        if((pending_brand.getId() != null && other.getPending_brand().getId() != null) &&
                pending_brand.getId().intValue() == other.getPending_brand().getId().intValue())
            brandIDsMatch = true;
    }
    if(species != null && other.getSpecies() != null) {
        if((species.getId() != null && other.getSpecies().getId() != null) &&
                species.getId().intValue() == other.getSpecies().getId().intValue())
            speciesIDsMatch = true;
    }
    if(brandIDsMatch && speciesIDsMatch)
        return true;
    else
        return false;
}
}

我填充相关物种集合的方法:

public void assignBrandSpecies(PendingBrandModel brandObj) {
        if(checkedSpeciesTypesStr != null) {
            String[] speciesList = checkedSpeciesTypesStr.split(ADDL_SEPARATOR);
            // Clear existing species
            if(brandObj.getSelected_species() != null)
                brandObj.getSelected_species().clear();
            // Add the roles the admin has chosen
            for(String speciesID : speciesList) {
                PendingBrandSpeciesModel newSpecies = new PendingBrandSpeciesModel();
                newSpecies.setPending_brand(brandObj);
                newSpecies.getSpecies().setId(Integer.parseInt(speciesID));
                if(brandObj.getSelected_species() == null)
                    brandObj.setSelected_species(new HashSet<PendingBrandSpeciesModel>());
                brandObj.getSelected_species().add(newSpecies);
            }
        }
    }

我已经尝试使用 .clear() 代码和没有它,但行为保持不变。 然后在它全部运行之后我更新品牌对象。

pendingBrandDAO.update(brandObj);

但是,无论我是否添加已使用的品牌 ID 和物种 ID 的组合,任何先前存在的记录都会保留在数据库中,并且会添加新记录。

【问题讨论】:

  • 您可以尝试从 PendingBrandModel 的集合中检索 PendingBrandSpeciesModel 并更新该对象。

标签: java database hibernate orm cascade


【解决方案1】:

我解决了重写 hashCode() 和 equals() 的类似问题。

【讨论】:

    【解决方案2】:

    您发布的代码不完整(...),但我的问题是它与 hashCode/equals 以及您的 id 在首次添加到集合时可能为空的事实有关。如果计算的 hashCode/equals 值在您第一次插入集合时发生了变化,则随后它将不会在集合中“找到”。根据您发布的代码,这只是一个粗略的猜测。也许完整的代码可以进一步澄清事情。

    这篇旧文章(参见下面的链接)在某种程度上被 hibernate 社区认为是“有争议的”,但无论如何它描述了一些可能的陷阱(即使建议的解决方案并不总是被一些 hibernate 顽固分子接受):

    Don't let hibernate steal your identity

    【讨论】:

      猜你喜欢
      • 2022-01-20
      • 2019-07-27
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多