JPA2 Lazy Child Collection с orphanRemoval = true удаляет «неполную» детей - PullRequest
2 голосов
/ 13 июля 2011

У меня есть родительский объект, которому принадлежит (через mappedBy) набор FetchType.LAZY с orphanDelete = true.

Клиент может успешно добавлять и удалять дочерние строки через получатель родительской коллекции, и их изменения правильно фиксируются после em.merge (parent).

Однако, если клиент объединяет родителя БЕЗ доступа к дочерней коллекции, все дочерние строки удаляются при фиксации родителя.

Такое же поведение демонстрируется в OpenJPA 2.1.0 и двоичном снимке 2.1.1-20110610.205956-18.

Любые указатели приветствуются.

Пример для иллюстрации:

@Entity
public class Parent{

    @Column
    private String name;

    @OneToMany(mappedBy="parent", fetch=LAZY, cascade = ALL, orphanRemoval=true)
    private Set<Child> children;

    public String getName(){return name;}
    public void setName(String name){this.name=name;}

    public Set<Child> getChildren(){
        return children;
    }
}

@Entity
public class Child{

    @ManyToOne(optional = false, targetEntity = Parent.class)
    @JoinColumn(name="parent_id", nullable=false)
    private Parent parent;

}

Обе сущности имеют объявленные свойства @Id и @Version и реализуют соответствующие методы hashCode, equals и compareTo.

Следующий код клиента работает отлично, имя parent.name обновлено, 1 дочерний элемент вставлен, а 1 дочерний элемент удален

EntityTransaction eTx=em.getTransaction();
eTx.begin();

Parent par=em.find(Parent.class, parId);
    //PersistenceUnitUtil.isLoaded(par) returns true
    //PersistenceUnitUtil.isLoaded(par, "children") returns false
Collection<Child> children=par.getChildren();
    //PersistenceUnitUtil.isLoaded(par, "children") returns true
Child child = children.iterator().next();
par.getChildren().remove(child);
par.getChildren().add(new Child(par, "I'm New"));
par.setName("I am Updated");
par=em.merge(par);

eTx.commit();

Следующий код выдаст команды удаления для каждого из потомков родителя:

EntityTransaction eTx=em.getTransaction();
eTx.begin();

Parent par=em.find(Parent.class, parId);
   //PersistenceUnitUtil.isLoaded(par) here returns true, and
   //PersistenceUnitUtil.isLoaded(par, "children") returns false
par.setName("I am Updated");
par=em.merge(par);
eTx.commit();

1 Ответ

0 голосов
/ 13 июля 2011

Только не вызывайте слияния. Там нет необходимости в этом. В рамках транзакции изменения, внесенные в объект, который был найден в этой транзакции, будут сохраняться, пока объект не будет отсоединен.

...