gpt4 book ai didi

Found shared references to a collection org.hibernate.HibernateException(找到对集合org.hibernate.HibernateException的共享引用)

转载 作者:bug小助手 更新时间:2023-10-25 16:49:48 31 4
gpt4 key购买 nike



I got this error message:

我收到以下错误消息:




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




When I tried to execute addToRelatedPersons(anotherPerson):

当我尝试执行addToRelatedPerson(另一个Person)时:



person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);

anotherPerson.save();
person.save();


My domain:

我的域名:



Person {

static hasMany = [relatedPersons:Person];

}


any idea why this happens ?

你知道为什么会发生这种事吗?


更多回答

I ran into the same exception, for me it was caused by having the same attribute twice in the inheritance path of my entity class

我遇到了相同的异常,对我来说,这是由于实体类的继承路径中有两次相同的属性造成的

I ran into the same problem as @kaefert (i.e. the same property more than once in inheritance path), but I got the exception only when the same criteria was run twice (calling list() twice). Tricky.

我遇到了与@kaefert相同的问题(即同一属性在继承路径中不止一次),但只有在相同的条件运行两次(调用list()两次)时才会出现异常。很棘手。

优秀答案推荐

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).

当您尝试持久化共享相同集合引用(即集合标识与集合相等相反)的多个实体实例时,Hibernate会显示此错误。



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?

请注意,它意味着相同的集合,而不是集合元素-换句话说,Person和另一个Person上的relatedPerson必须相同。也许您要在加载实体后重置该集合?或者您已经用相同的集合实例初始化了两个引用?



I had the same problem. In my case, the issue was that someone used BeanUtils to copy the properties of one entity to another, so we ended up having two entities referencing the same collection.

我也有同样的问题。在我的例子中,问题是有人使用BeanUtils将一个实体的属性复制到另一个实体,因此我们最终有两个实体引用同一个集合。



Given that I spent some time investigating this issue, I would recommend the following checklist:

鉴于我花了一些时间调查这个问题,我建议列出以下清单:




  • Look for scenarios like entity1.setCollection(entity2.getCollection()) and getCollection returns the internal reference to the collection (if getCollection() returns a new instance of the collection, then you don't need to worry).

    寻找类似entity1.setCollection(entity2.getCollection())和getCollection返回对集合的内部引用的场景(如果getCollection()返回集合的新实例,则无需担心)。


  • Look if clone() has been implemented correctly.

    查看是否正确实现了CLONE()。


  • Look for BeanUtils.copyProperties(entity1, entity2).

    查找BeanUtils.CopProperties(entity1,entity2)。




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);


Reading online the cause of this error can be also an hibernate bug, as workaround that it seems to work, it is to put a:

在线阅读这个错误的原因也可能是一个休眠错误,因为它似乎奏效了,它的解决方法是放一个:



session.clear()


You must to put the clear after getting data and before commit and close, see example:

您必须在获取数据之后以及提交和关闭之前进行清除,请参见示例:



//getting data
SrReq sr = (SrReq) crit.uniqueResult();
SrSalesDetailDTO dt=SrSalesDetailMapper.INSTANCE.map(sr);
//CLEAR
session.clear();
//close session
session.getTransaction().commit();
session.close();
return dt;


I use this solution for select to database, for update or insert i don't know if this solution can work or can cause problems.

我使用这个解决方案来选择数据库、更新或插入。我不知道这个解决方案是否可行,或者会不会引起问题。



My problem is equal at 100% of this: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html

我的问题在这个问题上是100%的:http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html



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.

检查容器的@Embedded ID是否存在可能的冲突。


Long version


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

当Hibernate实例化集合包装时,它通过内部映射中的CollectionKey搜索已经实例化的集合。


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

对于具有@Embedded id的实体,CollectionKey包装EmbeddedComponentType并使用@Embedded ID属性进行相等性检查和hashCode计算。


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.

因此,如果您有两个具有相同@Embedded ID的实体,Hibernate将按第一个键实例化并放置新集合,并将为第二个键找到相同的集合。因此,具有相同@Embedded ID的两个实体将使用相同的集合填充。


Example


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

假设你有一个账户实体,它有一套懒惰的贷款。Account Has@Embedded ID由几个部分(列)组成。


@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.

然后假设该帐户具有通过@Embedded ID映射的附加属性,但与其他实体分支有关。


@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.

可能发生的情况是,您没有用于Account to Brunch关系id DB的FK,因此Account.BRANCH列可以具有分支表格中未显示的任何值。


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

根据@NotFound(action=NotFoundAction.IGNORE),如果相关表中不存在值,Hibernate将为该属性加载空值。


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.

如果两个帐户的X和Y列相同(这很好),但分支不同并且不在分支表格中显示,则Hibernate将为两者加载NULL,并且嵌入的ID将相等。


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

因此,两个CollectionKey对象将是相等的,并且对于不同的帐户将具有相同的hashCode。


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.

因此,Hibernate将为两个实体加载相同的PesistentSet。



In my case, I was copying and pasting code from my other classes, so I did not notice that the getter code was bad written:

在我的例子中,我从其他类复制和粘贴代码,所以我没有注意到getter代码写得很糟糕:



@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito")
public Set getConceptoses() {
return this.letrases;
}

public void setConceptoses(Set conceptoses) {
this.conceptoses = conceptoses;
}


All references conceptoses but if you look at the get says letrases

所有引用都是概念性的,但如果你看一下GET就会说是Letrase



I too got the same issue, someone used BeanUtils.copyProperties(source, target). Here both source and target, are using the same collection as attribute.

我也遇到了同样的问题,有人使用了BeanUtils.Copy Properties(源、目标)。在这里,源和目标使用相同的集合作为属性。



So i just used the deep copy as below..

所以我只用了下面的深版..



How to Clone Collection in Java - Deep copy of ArrayList and HashSet

如何在Java中克隆集合-ArrayList和HashSet的深度复制



Consider an entity:

考虑一个实体:



public class Foo{
private<user> user;
/* with getters and setters */
}


And consider an Business Logic class:

并考虑一个Business Logic类:



class Foo1{
List<User> user = new ArrayList<>();
user = foo.getUser();
}


Here the user and foo.getUser() share the same reference. But saving the two references creates a conflict.

在这里,用户和foo.getUser()共享相同的引用。但保存这两个引用会产生冲突。



The proper usage should be:

正确的用法应该是:



class Foo1 {
List<User> user = new ArrayList<>();
user.addAll(foo.getUser);
}


This avoids the conflict.

这避免了冲突。



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

我在申请中遇到了类似的例外情况。查看堆栈跟踪后,很明显在FlushEntityEventListener类中抛出了异常。



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.

在Hibernate4.3.7中,MSLocalSessionFactory Bean不再支持eventListeners属性。因此,必须显式地从各个Hibernate会话Bean获取服务注册表,然后设置所需的自定义事件侦听器。



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.

在添加自定义事件侦听器的过程中,我们需要确保从相应的Hibernate会话中删除相应的默认事件侦听器。



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.

如果没有删除默认事件侦听器,则会出现两个事件侦听器针对同一事件注册的情况。在这种情况下,当迭代这些侦听器时,针对第一个侦听器,会话中的任何集合都将被标记为已到达,而针对第二个侦听器处理相同的集合时,将抛出此Hibernate异常。



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

因此,在注册自定义侦听器时,请确保从注册表中删除相应的默认侦听器。



My problem was that I had setup an @ManyToOne relationship. Maybe if the answers above don't fix your problem you might want to check the relationship that was mentioned in the error message.

我的问题是,我已经建立了@ManyToOne的关系。如果上面的答案不能解决您的问题,您可能需要检查错误消息中提到的关系。



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.

有可能,你也会遇到这个漏洞,这个漏洞自2017年以来一直存在,一直没有得到解决。


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.

老实说,我完全不知道如何绕过这个漏洞。我在这里发帖是为了我的理智,并希望能减少你几周的谷歌搜索时间。我喜欢任何人可能有的任何输入,但我对这个问题的特定“答案”没有在上面的任何答案中列出。



I had to replace the following collection initilization:

我不得不替换以下集合初始化:


challenge.setGoals(memberChallenge.getGoals());

with

使用


    challenge.setGoals(memberChallenge.getGoals()
.stream()
.map(dmo -> {
final ChallengeGoal goal = new ChallengeGoalImpl();
goal.setMemberChallenge(challenge);
goal.setGoalDate(dmo.getGoalDate());
goal.setGoalValue(dmo.getGoalValue());

return goal;
})
.collect(Collectors.toList()));


I changed

我变了


@OneToMany( cascade= CascadeType.ALL)

@JoinColumn(
name = "some_id",
referencedColumnName = "some_id"
)

to

@OneToMany(mappedBy = "some_id", cascade= CascadeType.ALL)


You're using pointers(indirectly), so sometimes you're copying the memory address instead of the object/collection you want. Hibernate checks this and throw that error. Here's what can you do:

您使用的是指针(间接),所以有时您复制的是内存地址,而不是您想要的对象/集合。Hibernate检查这一点并抛出那个错误。以下是您可以做的事情:



  1. Don't copy the object/collection;

  2. Initiate a new empty one;

  3. Make a function to copy it's content and call it;


For example:

例如:


public Entity copyEntity(Entity e){
Entity copy = new Entity();
e.copy(name);
e.setCollection2(null);
e.setCollection3(copyCollection(e.getCollection3());
return copy;
}


I was getting same error. And in my case, I had an incorrect relationship between my parent and child entities. I had @OneToMany, and changing it to @ManyToMany solved my problem.

我犯了同样的错误。在我的例子中,我在我的父母和孩子实体之间有一个不正确的关系。我有@OneToMany,把它改成@ManyToMany解决了我的问题。



It basically means that JPA doesn't want to save the exact same instance again, just being associated (set) to another object. Create a deep copy instead, and you should be fine.

这基本上意味着JPA不想再次保存完全相同的实例,只想关联(设置)到另一个对象。相反,创建一个深入的副本,你应该会很好。



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.

例如,每个人可以有多本书,但如果您认为一本书有多个所有者,则每本书只能由一个人拥有。


更多回答

found the problem. I did a mistake by typing person.relatedPerson = anotherPerson ; somewhere in the code .... doh.

找到问题了。我犯了一个错误,在代码中的某个地方键入了Pers.relatedPerson=anther Person;...多伊尔。

yes, but why hibernate treats this as a problem? An entity has a collection like a ManyToMany field, and the value is set by looking up from another entity.

是的,但是为什么Hibernate把这当作一个问题呢?实体有一个类似于ManyToMany字段的集合,该值是通过从另一个实体查找来设置的。

Look for that type of issues vary carefully, my case was quite hard to find. In my code I had few entities, of types A, B, C, D. There are relations between them A oneToOne B B oneToMany C - collection of Cs is fetched lazily there C oneToMany D - collection of Ds is fetched eagerly there In code there was a call using collection of Cs. Because of that call, collection of Cs was fetched, and some of them had same references to collections of Ds. Then instance of A was saved, which also saved B, with collection of Cs (and in some cases Cs had reference to same Ds collection).

仔细寻找那种类型的问题各不相同,我的情况相当难找。在我的代码中,我有几个实体,类型是A,B,C,D,它们之间有关系A,to,B,B,to,one,to,one,to,I,to,one,to,I,I,由于该调用,获取了C的集合,并且其中一些对D的集合具有相同的引用。然后保存A的实例,这也保存了B和Cs的集合(在某些情况下,Cs引用了相同的DS集合)。

what class should implement clone() ?

哪个类应该实现Clone()?

@vacuum, the domain model.

@Vacuum,域名模型。

what would be the solution here?

这里的解决方案是什么?

@vashishth Earlier, I was doing entity1.setCollection(entity2.getCollection()). I solved it by entity1.setCollection(new HashSet(entity2.getCollection()))

@vashishth之前,我在做entity1.setCollection(entity2.getCollection()).我通过entity1.setCollection(new HashSet(entity2.getCollection()解决了它

Thanks for the checklist. In my case I was doing BeanUtils.copyProperties(oldRec, newRec) in 'clone()` method. I updated the BeanUtils.copyProperties to skip the newly added ManyToMany field as BeanUtils.copyProperties(oldRec, newRec, newCollectionField).

谢谢你的核对表。在我的例子中,我在‘Clone()’方法中执行BeanUtils.CopProperties(oldRec,newRec)。我更新了BeanUtils.CopProperties以跳过新添加的作为BeanUtils.CopProperties(oldRec,newRec,newCollectionfield)的ManyToMany字段。

You saved my day. I had the same issue, but because of non-unique composite key for many-to-many relation. Thanks a lot! Where can I read about this Hibernate feature?

你拯救了我的一天。我也遇到了同样的问题,但因为多对多关系的组合键不是唯一的。非常感谢!我在哪里可以读到有关休眠功能的信息?

I am sorry, but this is not really helpful as it's just a simple mistake on your side.

我很抱歉,但这是不是真的有帮助,因为它只是一个简单的错误,在你的身边。

This is unnecessarily hard to read because class names are lower case and the code contains unnecessary assignments.

这不必要地难以阅读,因为类名是小写的,并且代码包含不必要的赋值。

Could you please edit to make this a little more readable?

能不能请你修改一下,让这个更具可读性?

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com