2012-06-25 3 views
0

Вот мой кодJPA - Invalid дубликат вставки

@Entity 
class Parent extends Person { 
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "father") 
    private List<Child> children; 

    // ... 

    public void addChild(Child c) { 
     children.add(c); 
    } 

} 

@Entity 
class Child extends Person { 
    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name = "id") 
    private Parent father; 

    public Child() { 
     this(NoParent.getInstance());// 
    } 

    public Child(Parent p) { 
     super(); 
     setParent(p); 
    } 

    // ... 
} 

@MappedSuperclass 
class Person { 
    @Id 
    private Integer id; 
    private String name; 
} 

class MyParentService { 

    public void addChild(String name, Parent parent) { 
     Child c = new Child(parent); 
     c.setName(name); 
     parent.addChild(c); 

     em.getTransaction.begin(); 
     em.merge(parent); 
     em.getTransaction.commit();// Here two children with same name but different ids are created ... 
    } 
}  

Каждый раз, когда я запускаю его, двое детей добавляются в базу данных, а я просто хочу один!
Что я делаю неправильно?

Java 6
JPA 2
Hibernate 3.6.8.GA

+0

Можете ли вы добавить код для конструктора Child, который получает родительский элемент, а также метод addChild для родителя? – jpkrohling

+0

@partenon Я обновил свой код с помощью кода конструктора и метода. – Stephan

+0

Можете ли вы добавить код для setParent of Child? Если в этом есть вызов addChild of Parent, новый ребенок будет добавлен дважды. – Gandalf

ответ

1

Я прочитал документацию Hibernate, которая действительно сбивает с толку и не очень мне помогла.

Обратите внимание, что я обнаружил, что ObjectDB недавно столкнулся с AND fixed the exact same bug. (Hibernate, ребята, почему вы ждали так долго ??)

Тем не менее, здесь решение, которое я придумал:

ШАГ 1:
Создать свежий ребенка (т.е. в отдельных состоянии) и вызовите метод setParent для ссылки на родителя.

ШАГ 2:
Сохранять этот ребенок.

ШАГ 3:
Внести изменения в ребенка, как вам нужно, и объединить его позже.

Решение довольно элегантное, но оно работает! Далее вы получите свой родительский объект, у него будет связанный с ним ранее дочерний (ren).

2

Вы случайно сохраняющегося ребенка после того, как родитель? Кроме того, наилучшей практикой является управление связыванием объектов только со стороны владельца отношений (как с parent.addChild, так и с child.setParent одним способом), но это не кажется важным в вашем случае, поскольку объекты связаны должным образом к моменту возникновения «слияния». Если ни одно из этих действий не работает, вы можете это сделать: https://hibernate.onjira.com/browse/HHH-5855

+0

Я создаю новый свежий ребенок (оператор 'new'), добавьте его в родительский. Тем не менее, я посмотрел на ошибку, и никакие обходные пути, похоже, не работают для меня. Я никогда не получаю ни одной записи о ребенке, одна дочерняя запись не обновляется или хуже двух дочерних записей: до и после обновления записи. – Stephan

Смежные вопросы