nig*_*2k1 59 java grails groovy hibernate grails-orm
我收到此错误消息:
error:找到对集合的共享引用:Person.relatedPersons
当我试图执行时addToRelatedPersons(anotherPerson)
:
person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);
anotherPerson.save();
person.save();
Run Code Online (Sandbox Code Playgroud)
我的域名:
Person {
static hasMany = [relatedPersons:Person];
}
Run Code Online (Sandbox Code Playgroud)
知道为什么会这样吗?
Chs*_*y76 63
当您尝试持久存在多个共享相同集合引用的实体实例(即集合标识与集合相等性)时,Hibernate会显示此错误.
请注意,这意味着同样的集合,而不是集合元素-换句话说,relatedPersons
在两个person
和anotherPerson
必须相同.也许你在加载实体后重置那个集合?或者您已使用相同的集合实例初始化两个引用?
dgt*_*dgt 50
我有同样的问题.在我的例子中,问题是有人使用BeanUtils将一个实体的属性复制到另一个实体,因此我们最终有两个实体引用同一个集合.
鉴于我花了一些时间研究这个问题,我建议如下清单:
查找类似的场景entity1.setCollection(entity2.getCollection())
并getCollection
返回对集合的内部引用(如果getCollection()返回集合的新实例,那么您不必担心).
看看是否clone()
已正确实施.
寻找BeanUtils.copyProperties(entity1, entity2)
.
练习说明。如果您尝试保存对象,例如:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);
Run Code Online (Sandbox Code Playgroud)
您不需要将更新的对象设置为父对象:
message.setFiles(folders);
Run Code Online (Sandbox Code Playgroud)
简单保存您的父对象,如:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
// Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
Run Code Online (Sandbox Code Playgroud)
我经历过一个重现此类问题的好例子。也许有一天我的经验会对某人有所帮助。
检查容器的 @Embedded Id 是否存在可能的冲突。
当Hibernate实例化集合包装器时,它会在内部Map中通过CollectionKey搜索已经实例化的集合。
对于带有@Embedded id的Entity,CollectionKey包装EmbeddedComponentType并使用@Embedded Id属性进行相等性检查和hashCode计算。
因此,如果您有两个具有相同 @Embedded Id 的实体,Hibernate 将实例化并通过第一个键放置新集合,并为第二个键找到相同的集合。因此具有相同 @Embedded Id 的两个实体将使用相同的集合填充。
假设您有一个包含惰性贷款集的帐户实体。并且Account有@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;
...
}
Run Code Online (Sandbox Code Playgroud)
然后假设 Account 具有由 @Embedded Id 映射的附加属性,但与其他实体 Branch 相关。
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "BRANCH")
@MapsId("accountId.branchId")
@NotFound(action = NotFoundAction.IGNORE)//Look at this!
private Branch branch;
Run Code Online (Sandbox Code Playgroud)
可能会发生这样的情况:帐户到 Brunch 关系 id 数据库没有 FK,因此 Account.BRANCH 列可以具有 Branch 表中未显示的任何值。
根据@NotFound(action = NotFoundAction.IGNORE)
相关表中是否存在值,Hibernate 将加载该属性的空值。
如果两个帐户的 X 和 Y 列相同(这很好),但 BRANCH 不同并且未出现在 Branch 表中,hibernate 将为两个帐户加载null,并且嵌入式 Id 将相等。
因此,两个 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"
Run Code Online (Sandbox Code Playgroud)
因此,Hibernate 将为两个实体加载相同的 PecientSet。
在线阅读引起此错误的原因也可能是休眠错误,因为似乎可以解决该问题的方法是,将以下内容放入:
session.clear()
Run Code Online (Sandbox Code Playgroud)
您必须在获取数据之后,提交和关闭之前进行清除,请参见示例:
//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;
Run Code Online (Sandbox Code Playgroud)
我使用此解决方案选择数据库,进行更新或插入,但我不知道此解决方案是否可以工作或会导致问题。
我的问题等于100%:http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html
归档时间: |
|
查看次数: |
84792 次 |
最近记录: |