Found shared references to a collection org.hibernate.HibernateException

前端 未结 12 1231
一整个雨季
一整个雨季 2020-11-27 15:48

I got this error message:

error: Found shared references to a collection: Person.relatedPersons

When I tried to execute ad

相关标签:
12条回答
  • 2020-11-27 16:18

    I have experienced a great example of reproducing such a problem. Maybe my experience will help someone one day.

    Short version

    Check that your @Embedded Id of container has no possible collisions.

    Long version

    When Hibernate instantiates collection wrapper, it searches for already instantiated collection by CollectionKey in internal Map.

    For Entity with @Embedded id, CollectionKey wraps EmbeddedComponentType and uses @Embedded Id properties for equality checks and hashCode calculation.

    So if you have two entities with equal @Embedded Ids, Hibernate will instantiate and put new collection by the first key and will find same collection for the second key. So two entities with same @Embedded Id will be populated with same collection.

    Example

    Suppose you have Account entity which has lazy set of loans. And Account has @Embedded Id consists of several parts(columns).

    @Entity
    @Table(schema = "SOME", name = "ACCOUNT")
    public class Account {
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "account")
        private Set<Loan> loans;
    
        @Embedded
        private AccountId accountId;
    
        ...
    }
    
    @Embeddable
    public class AccountId {
        @Column(name = "X")
        private Long x;
        
        @Column(name = "BRANCH")
        private String branchId;
        
        @Column(name = "Z")
        private String z;
    
        ...
    }
    

    Then suppose that Account has additional property mapped by @Embedded Id but has relation to other entity Branch.

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "BRANCH")
    @MapsId("accountId.branchId")
    @NotFound(action = NotFoundAction.IGNORE)//Look at this!
    private Branch branch;
    

    It could happen that you have no FK for Account to Brunch relation id DB so Account.BRANCH column can have any value not presented in Branch table.

    According to @NotFound(action = NotFoundAction.IGNORE) if value is not present in related table, Hibernate will load null value for the property.

    If X and Y columns of two Accounts are same(which is fine), but BRANCH is different and not presented in Branch table, hibernate will load null for both and Embedded Ids will be equal.

    So two CollectionKey objects will be equal and will have same hashCode for different Accounts.

    result = {CollectionKey@34809} "CollectionKey[Account.loans#Account@43deab74]"
     role = "Account.loans"
     key = {Account@26451} 
     keyType = {EmbeddedComponentType@21355} 
     factory = {SessionFactoryImpl@21356} 
     hashCode = 1187125168
     entityMode = {EntityMode@17415} "pojo"
    
    result = {CollectionKey@35653} "CollectionKey[Account.loans#Account@33470aa]"
     role = "Account.loans"
     key = {Account@35225} 
     keyType = {EmbeddedComponentType@21355} 
     factory = {SessionFactoryImpl@21356} 
     hashCode = 1187125168
     entityMode = {EntityMode@17415} "pojo"
    

    Because of this, Hibernate will load same PesistentSet for two entities.

    0 讨论(0)
  • 2020-11-27 16:18

    I faced similar exception in my application. After looking into the stacktrace it was clear that exception was thrown within a FlushEntityEventListener class.

    In Hibernate 4.3.7 the MSLocalSessionFactory bean no longer supports the eventListeners property. Hence, one has to explicitly fetch the service registry from individual Hibernate session beans and then set the required custom event listeners.

    In the process of adding custom event listeners we need to make sure the corresponding default event listeners are removed from the respective Hibernate session.

    If the default event listener is not removed then the case arises of two event listeners registered against same event. In this case while iterating over these listeners, against first listeners any collections in the session will be flagged as reached and while processing the same collection against second listener would throw this Hibernate exception.

    So, make sure that when registering custom listeners corresponding default listeners are removed from registry.

    0 讨论(0)
  • 2020-11-27 16:18

    Posting here because it's taken me over 2 weeks to get to the bottom of this, and I still haven't fully resolved it.

    There is a chance, that you're also just running into this bug which has been around since 2017 and hasn't been addressed.

    I honestly have no clue how to get around this bug. I'm posting here for my sanity and hopefully to shave a couple weeks of your googling. I'd love any input anyone may have, but my particular "answer" to this problem was not listed in any of the above answers.

    0 讨论(0)
  • 2020-11-27 16:22

    In a one to many and many to one relationship this error will occur. If you attempt to devote same instance from many to one entity to more than one instance from one to many entity.

    For example, each person can have many books but each of these books can be owned by only one person if you consider more than one owner for a book this issue is raised.

    0 讨论(0)
  • 2020-11-27 16:23

    Explanation on practice. If you try to save your object, e.g.:

    Set<Folder> folders = message.getFolders();
       folders.remove(inputFolder);
       folders.add(trashFolder);
       message.setFiles(folders);
    MESSAGESDAO.getMessageDAO().save(message);
    

    you don't need to set updated object to a parent object:

    message.setFiles(folders);
    

    Simple save your parent object like:

    Set<Folder> folders = message.getFolders();
       folders.remove(inputFolder);
       folders.add(trashFolder);
       // Not set updated object here
    MESSAGESDAO.getMessageDAO().save(message);
    
    0 讨论(0)
  • 2020-11-27 16:25

    Hibernate shows this error when you attempt to persist more than one entity instance sharing the same collection reference (i.e. the collection identity in contrast with collection equality).

    Note that it means the same collection, not collection element - in other words relatedPersons on both person and anotherPerson must be the same. Perhaps you're resetting that collection after entities are loaded? Or you've initialized both references with the same collection instance?

    0 讨论(0)
提交回复
热议问题