Hibernate inserts duplicates into a @OneToMany collection

前端 未结 5 1627
野性不改
野性不改 2020-12-01 20:52

I have a question concerning Hibernate 3.6.7 and JPA 2.0.

Consider following entities (some getters and setters are omitted for brevity):

@Entity
pub         


        
相关标签:
5条回答
  • 2020-12-01 21:33

    Managed this by just calling the empty() method. For this scenario,

    parent.getChildren().isEmpty()

    before

    parent.getChildren().add(child);
    
    0 讨论(0)
  • 2020-12-01 21:39

    By using Java enterprise context in Wildfly (8.2.0-Final) (I think it's Hibernate version 4.3.7) the workaround for me was, to first persist the child an the add it to the lazy collection:

    ...
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void test(){
        Child child = new Child();
        child.setParent(parent);
        childFacade.create(child);
    
        parent.getChildren().add(cild);
    
        parentFacade.edit(parent);
    }
    
    0 讨论(0)
  • 2020-12-01 21:40

    I fixed this problem by telling Hibernate not to add duplicates in my collection. In your case change the type of your children field from List<Child> to Set<Child> and implement equals(Object obj) and hashCode() on the Child class.

    Obviously this will not be possible in every case, but if there is a sane way to identify that a Child instance is unique then this solution can be relatively painless.

    0 讨论(0)
  • 2020-12-01 21:41

    It's a bug in Hibernate. Surprisingly, it's not reported yet, feel free to report it.

    Operations against non-initialized lazy collections are queued in order to execute them after collection is initialized, and Hibernate doesn't handle the situation when these operations conflict with the data from the database. Usually it's not a problem, because this queue is cleared upon flush(), and possible conflicting changes are propagated to the database upon flush() as well. However, some changes (such as persisting of entities with ids generated by generator of type IDENTITY, I guess, it's your case) are propagated to the database without the full flush(), and in these cases conflicts are possible.

    As a workaround you can flush() the session after persisting the child:

    em.persist(child); 
    em.flush();
    
    0 讨论(0)
  • 2020-12-01 21:45

    I came across this question when I had issues not with adding items to a list annotated with @OneToMany, but when trying to iterate over the items of such a list. The items in the list were always duplicated, sometimes a lot more than twice. (Also happened when annotated with @ManyToMany). Using a Set was not a solution here, since these lists were supposed to allow duplicate elements in them.

    Example:

    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    @Cascade(CascadeType.ALL)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List entities;
    

    As it turned out, Hibernate executes sql statements using left outer join, which can result in duplicate results returned by the db. What helped was simply defining an ordering on the result, using OrderColumn:

    @OrderColumn(name = "columnName")
    0 讨论(0)
提交回复
热议问题