Found shared references to a collection org.hibernate.HibernateException

前端 未结 12 1347
一整个雨季
一整个雨季 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 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.

提交回复
热议问题