JPA Hibernate:实体副本[xxx]已经分配给不同的实体[yyyyy]

时间:2014-04-05 06:43:51

标签: java entity-framework hibernate jpa playframework

最近,当我在播放2.2.1 JPA(1.3.0.final) Hibernate(4.2.6.final) >框架,我得到了错误:

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

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

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

我有三个实体,所有者项目

假设:

  1. 项目或方框必须拥有所有者;
  2. Box可能包含零个或多个Items,而特定Item可能不属于任何Box。
  3. 当一个物品放入一个盒子时,它们可能有也可能没有相同的所有者。
  4. 实体类:

    / *为简单起见,省略了其他字段,getter和setter * /

    简化的所有者类定义

        @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*/
        }
    
    }
    

    有没有人有任何想法解决这个问题?

    感谢。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。通过添加对我有用的链接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>

干杯!