【发布时间】:2014-04-05 06:43:51
【问题描述】:
最近,当我在 Play 2.2.1 上使用 JPA(1.3.0.final) 和 Hibernate(4.2.6.final) 时> 框架,我收到如下错误:
java.lang.IllegalStateException:存储实体 [xxx] 时出错 实体副本 [xxx] 已分配给不同的实体 [yyy]
互联网上现有的解决方案都没有解决我的问题。
现在,让我解释一下这个故事。
我有三个实体,Owner、Box和Item。
假设:
- 物品或盒子必须有所有者;
- 一个 Box 可能包含零个或多个 Item,而特定 Item 可能不属于任何 Box。
- 将物品放入盒子时,它们的所有者可能相同,也可能不同。
实体类:
/* 为简单起见,其他字段,getter 和 setter 被省略*/
简化的 Owner 类定义
@Entity
@Table(name = "OWNER")
public class Owner implements Serializable{
@Id
@Column(name="ID")
public String uuid = UUID.randomUUID().toString();
@Override
public int hashCode() {
int result = 1;
char[] charArray = this.uuid.toCharArray();
int n = charArray.length;
int powbase = (int) Math.pow(31, n - 1);
for(int i = 0; i < n; i++){
if ( i != 0){
powbase = powbase / 31;
}
result += (int)charArray[i] * powbase;
}
return result;
}
@Override
public boolean equals(Object obj) {
if(obj == null){
return false;
}
if(!(obj instanceof Item)){
return false;
}
Item other = (Item)obj;
//Box other = (Box)obj;
//Owner other = (Owner)obj;
if(!other.uuid.equals(this.uuid)){
return false;
}
return true;
}
}
Item和Box的hashCode()和equals()的实现与Owner类似。为了论证起见,让我们省略这些。
简化的 Item 类定义
@Entity
@Table(name = "ITEM")
public class Item implements Serializable{
@Id
@Column(name="ID")
public String uuid = UUID.randomUUID().toString();
/* single-directional mapping*/
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "O_ID")
public Owner owner;
/* bi-directional mapping*/
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "B_ID")
public Box box;
}
简化的 Box 类定义。
@Entity
@Table(name = "BOX")
public class Box implements Serializable {
@Id
@Column(name="ID")
public String uuid = UUID.randomUUID().toString();
/* single-directional mapping*/
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "O_ID")
public Owner owner;
/* bi-directional mapping*/
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER, mappedBy = "box")
public Set<Item> items = new HashSet<Item>();
}
业务逻辑如下:
public class Test {
public static void main(String[] args) {
Owner owner = new Owner();
JPA.em().persist(owner);
Box box = new Box();
box.owner = owner;
JPA.em().persist(box);
Item boxItem = new Item();
boxItem.owner = owner;
boxItem.box = box;
box.items.add(boxItem);
JPA.em().persist(boxItem);
Item nonBoxItem = new Item();
nonBoxItem.owner = owner;
JPA.em().persist(nonBoxItem);
/* in the future, put the 'nonBoxItem' into a box*/
Item itemToUpdate = JPA.em().find(Item.class, nonBoxItem.uuid);
itemToUpdate.box = box;
box.items.add(itemToUpdate);
JPA.em().merge(itemToUpdate); /* error occurred here*/
}
}
有没有人想办法解决这个问题?
谢谢。
【问题讨论】:
标签: java entity-framework hibernate jpa playframework