最近,当我在Play 2.2.1框架上使用JPA(1.3.0.final)和Hibernate(4.2.6.final)时,出现如下错误:

java.lang.IllegalStateException:存储实体[xxx]时发生错误,实体副本[xxx]已分配给另一个实体[yyy]

互联网上的现有解决方案都无法解决我的问题。

现在,让我解释一下这个故事。

我有三个实体,所有者,盒子和物品。

假设:


物品或盒子必须具有所有者;
一个Box可能包含零个或多个项目,而特定的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*/
    }

}


有谁有解决这个问题的想法?

谢谢。

最佳答案

我有同样的问题。通过添加对我有用的此链接https://stackoverflow.com/questions/17634230/hibernate-an-entity-copy-was-already-assigned-to-a-different-entity的依赖关系来解决

<dependency>
<groupId>com.intersult</groupId>
<artifactId>jpa-fix</artifactId>
<version>1.1</version>




干杯!

09-10 08:54
查看更多