简体   繁体   中英

Hibernate how to remove item from list

I have been facing some challenges of understanding how list are managed in hibernate.

I have looked at the following post: hibernate removing item from a list does not persist but that did not help.

So here is the parent:

public class Material extends MappedModel implements Serializable
{
    /**
     * List of material attributes associated with the given material
     */
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @JoinColumn(name = "material_id", nullable = false)
    @org.hibernate.annotations.IndexColumn(name = "seq_number", base = 0)
    private List<MaterialAttribute> materialAttributes = new ArrayList<MaterialAttribute>();

here is the child

public class MaterialAttribute extends MappedModel implements Serializable

{
    /**
     * identifies the material that these attributes are associated with
     */
    @ManyToOne
    @JoinColumn(name = "material_id", nullable=false, updatable=false, insertable=false)
    private Material material;

So in my Service class I am doing the following:

public void save(MaterialCommand pCmd)
{
Material material = new Material();
if(null != pCmd.getMaterialId())
{
    material = this.loadMaterial(pCmd.getMaterialId());
}

material.setName(pCmd.getName());
material.getMaterialAttributes().clear();

    List<MaterialAttribute> attribs = new ArrayList<MaterialAttribute>();
    if(CollectionUtils.isNotEmpty(pCmd.getAttribs()))
    {
        Iterator<MaterialAttributeCommand> iter = pCmd.getAttribs().iterator();
        while(iter.hasNext())
        {
MaterialAttributeCommand attribCmd = (MaterialAttributeCommand) iter.next();
            if (StringUtils.isNotBlank(attribCmd.getDisplayName()))
{
        MaterialAttribute attrib = new MaterialAttribute();
        attrib.setDisplayName(attribCmd.getDisplayName());
        attrib.setValidationType(null);
        attribs.add(attrib);
}
        }
    }

    material.setMaterialAttributes(attribs);
    this.getMaterialDao().update(material);
}

So with the above set up the first time everything is created in the database correctly. The second time, my expectation was that the the first set of items in the collection would of been removed and only the new items would be in the database. That did not happen. The original items in the child are there along with the the new items and that that the seq number start at 0 again.

Also, I am seeing the following error

org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance:

What am I missing.

Implementation of DELETE_ORPHAN applies some restrictions on operations with collection. In particular, you shouldn't replace that collection with another instance of collection. Add new items to the existing collection instead:

material.getMaterialAttributes().clear();
... 
material.getMaterialAttributes().addAll(attribs); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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