2015-06-17 6 views
3

Я определил два класса: «Родительский и детский». Родитель может иметь список детей.Однонаправленное преобразование «один ко многим» в Hibernate генерирует избыточные обновления.

@Entity 
public class Parent { 
    @Id 
    @GeneratedValue(...) 
    @SequenceGenerator(...) 
    private long id; 

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false) 
    private List<Child> children; 

    public Parent() { 
     children = new ArrayList<Child>(); 
    } 

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

@Entity 
public class Child { 
    @Id 
    @GeneratedValue(...) 
    @SequenceGenerator(...) 
    private long id; 

    // The "Child" table in the db also has a not-null "parent_id" column. 
} 

Если добавить кучу детей в список и сохраняться родитель все работает, как ожидалось: Hibernate получает значения последовательности, сохраняет родителя и затем сохраняет все дети.

Однако, выполнив все это, он обновит все дочерние элементы, установив «parent_id» на значение, которое уже было установлено во вставке!

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

insert into PARENT (id) values (1) 
insert into CHILD (parent_id, id) values (1, 1) 
insert into CHILD (parent_id, id) values (1, 2) 
insert into CHILD (parent_id, id) values (1, 3) 
update CHILD set parent_id = 1 WHERE id = 1 
update CHILD set parent_id = 1 WHERE id = 2 
update CHILD set parent_id = 1 WHERE id = 3 

Если я это объединение двунаправленным он работает отлично, но тогда мне нужна ссылка на родитель в моем классе ребенка и что-то я хочу, чтобы избежать.

Хранилище представляет собой хранилище Spring Data JPA:

public interface ParentRepository extends PagingAndSortingRepository<Parent, Long> {} 

The (упрощенный) код, который создает и сохраняет объекты:

Parent parent = new Parent(); 
parent.addChild(new Child()); 
parent.addChild(new Child()); 
repo.save(parent); 

Любые предложения?

+0

@chsdk, чем дополнительный код вам нужно? Если это помогает, я использую репозиторий Spring Data JPA, на который я вызываю save (parent). Как родитель, так и дети полностью неизменяемы после создания с помощью строителя. –

+0

Попробуйте добавить 'mappedBy' атрибут к вашему сопоставлению следующим образом:' @OneToMany (mappedBy = "parent", fetch = FetchType.EAGER, cascade = CascadeType.ALL) 'где parent должно быть именем поля Parent в Child класс. –

+0

@chsdk, как я уже упоминал в вопросе, у меня нет ссылки на родителя в моем ребенке. Это однонаправленная ассоциация. –

ответ

1

Вы пробовали:

@JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false, insertable=false, updatable=false) 
+0

Спасибо, это действительно работает! Семантика немного запутанна, но я понимаю, что вы добавляете эти параметры, потому что ребенок уже вставляет/обновляет себя (из-за каскада), и родитель также не должен это делать? –

+1

таким образом не будет вставлять FK в таблицу. Если вам нужны значения FK, вы должны поставить yes в insertable/updatable. :) –

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