Уменьшение количества запросов JPA, выполняемых при вставке

У меня есть однонаправленное отношение «один ко многим» родитель-потомок. В моем тестовом примере у меня есть 1 родитель с 2 дочерними элементами, которые вставляются через каскадную вставку.

Глядя на выполненные запросы, у меня есть 1 вставка для родителя, 1 вставка и два запроса на обновление для каждого из дочерних элементов. Обновления для внешнего ключа - они устанавливают столбец parent_id в дочерней таблице, но я вижу, что parent_id уже был правильно установлен вставкой.

Вот пример

@Entity
@Table(name = "PARENT")
public class Parent
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long parentId;

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

@Entity
@Table(name = "CHILD")
public class Child 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @Column(name = "PARENT_ID")
    private Long parentId;

    //some other field
}

//The test looks like this

Parent parent = new Parent();
Child child1 = new Child();
Child child2 = new Child();
//set all fields

parent.addChild(child1);
parent.addChild(child2);

em.merge(parent);

Можно ли не иметь запросов на обновление? Можно ли вставить всех дочерних элементов в один запрос?


person ventsyv    schedule 19.11.2015    source источник
comment
Как вы их вставляете? Объединить или сохранить? Разместите код.   -  person mikeb    schedule 19.11.2015
comment
Объединить. Код тривиален, я просто вызываю слияние родительского объекта.   -  person ventsyv    schedule 19.11.2015
comment
тривиально Ну, да, и да, это не так - если вы используете готовый процесс в API для автоматизации этих связанных операторов, но вы пытаетесь смягчить то, что составляет отказоустойчивые вызовы, то тривиальность - это не то, как я бы это описал . Обновления (из того, что я помню о своих днях java, около 3 лет назад) существуют для обеспечения непрерывности - я печатаю медленно - Анудж опередил меня - но в основном в распределенной системе родительский объект / таблица доступны потенциально раньше, чем ребенок и обновления являются необходимостью   -  person Brandt Solovij    schedule 19.11.2015


Ответы (2)


Вы можете попробовать persist вместо merge

JPA EntityManager: зачем использовать persist() вместо merge()?

person mikeb    schedule 19.11.2015

Нет, это невозможно. потому что после вставки в родительскую таблицу можно вставить дочернюю таблицу.

person Anuj Panwar    schedule 19.11.2015
comment
Это не имеет смысла (по крайней мере, на уровне SQL). Если родитель вставлен перед дочерними элементами, то PK родителя наверняка известен, и нет необходимости запускать одно обновление для каждого дочернего элемента после их вставки. - person a_horse_with_no_name; 19.11.2015
comment
@a_horse_with_no_name - если родительскому элементу не назначена блокировка во время обновления/создания - вы можете увидеть состояние гонки (и, вероятно, произойдет) в любой системе с умеренным одновременным использованием - person Brandt Solovij; 19.11.2015
comment
Я согласен. У меня включено ведение журнала, и я вижу не только то, что вставляется родительская строка, но и то, что дочерняя строка вставляется С правильным родительским идентификатором. Обновления совершенно не нужны. - person ventsyv; 19.11.2015
comment
@BrandtSolovij: родитель не виден за пределами транзакции, поэтому блокировать его бесполезно. И дочерние строки также не видны вне транзакции, поэтому блокировка также не требуется. Так откуда же должно появиться состояние гонки? - person a_horse_with_no_name; 19.11.2015