JPA / Eclipselink сущность пакетного обновления с низкой производительностью при изменениях отношений ManyToOne - PullRequest
2 голосов
/ 10 декабря 2010

У меня проблема с пакетной записью в eclipselink, когда я обновляю свойства сущности, которые ссылаются на другую сущность.

У меня есть сущность держателя карты с отношением @ManyToOne и сущностью карты.

@Entity
@Table(name = "...")
@NamedQueries({...})
public class Cardholder implements Serializable {
  ...
  @JoinColumn(name = "card_number", referencedColumnName = "...")
  @ManyToOne(fetch=FetchType.LAZY)
  private Card card;
}

и Карта с отношениями @OneToMany с владельцем карты

@Entity
@Table(name = "cms_card")
@NamedQueries({...})
public class Card implements Serializable {
    @OneToMany(mappedBy = "card")
    private List<Cardholder> cardholderList;
}

У меня уже есть Список детей (постоянные владельцы карт).Теперь я хочу добавить к ним некоторую карту, поэтому: // cardholderList - это список управляемых объектов.

for (Cardholder cardholder : cardholderList) {
  Card newCard = new Card();
  ...
  cardholder.setCard(newCard);
  List<Cardholder> cardCardholders = new ArrayList<Cardholder>();
  cardCardholders.add(cardholder);
  newCard.setCardholderList(cardCardholders);
  cardsToBePersisted.add(newCard);
  ++i;
}

Я настроил свой Persistence.xml для использования пакетной записи, но производительность + ужасно низкая для + -15000 обновлений списка.Теперь, когда я проверяю сгенерированный SQL, я обнаружил, что Eclipselink создает один пакет для одного запроса, например:

FINER: Begin batch statements
FINE: INSERT INTO cms_card (card_number, status, chip_serial_number, dwh_status, valid_until, card_holder_id, file_perso_history_id, feedback_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
FINE:         bind => [9030002005890011, ACTIVE, null, false, 2015-12-10, null, 241, null]
FINER: End Batch Statements
FINER: Begin batch statements
FINE: UPDATE cms_cardholder SET card_number = ? WHERE (id = ?)
FINE:         bind => [9030002005890011, 176075]
FINER: End Batch Statements
FINER: Begin batch statements
FINE: INSERT INTO cms_card (card_number, status, chip_serial_number, dwh_status, valid_until, card_holder_id, file_perso_history_id, feedback_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
FINE:         bind => [9030002005889908, ACTIVE, null, false, 2015-12-10, null, 241, null]
FINER: End Batch Statements

Я думаю, это потому, что я установил новое родительское свойство (карточку) для существующих потомков.

Я также пытаюсь изменить отношения родителя и ребенка (владелец карты-> карта вместо карты-> держатель карты).Пакетная вставка верна после того, как я изменил отношение в сущности и базе данных, но Eclipselink все равно запросит базу данных (SELECT * с карты, где cardholder.id =?), Поэтому для 15000 записей я получил 15000 операторов выбора.Лучше, чем выше, но все еще очень и очень медленно.

Есть ли какая-то ошибка, которую я допустил при настройке пакетной записи?Большое спасибо.

Ответы [ 2 ]

1 голос
/ 23 марта 2011

Каковы все отношения в Карте и Владельце карточки?

Похоже, у вас есть цикл между двумя классами, поэтому EclipseLink должен выпустить обновление, чтобы разрешить цикл.

Выесть card_holder_id в вашей Карте и card_number в вашем CardHolder?Почему у вас есть чужой ключ в обеих таблицах?Если вы исправите свой цикл, то вставки можно будет сгруппировать и разрешить оптимальную дозировку.

Не уверены, что вы делаете, чтобы получить выбор?Это новые объекты, они отмечают?Или ты тоже обновляешься?

0 голосов
/ 22 марта 2011

Я не совсем уверен в причине вашей проблемы, но я бы посоветовал сделать следующее:

Если у меня есть ситуации oneToMany и manyToOne, и это связано с большим количеством данных для сбора, я буду избегать использованияколлекция, чтобы добавить детали [s], поскольку она может инициировать заполнение коллекции, когда в этом нет необходимости, что может стать источником проблем с производительностью.

Простой пример, который поможет проиллюстрировать то, что я имел в виду: Рассмотрим 2 сущностиКоманда и игрок. У команды есть список игроков (один ко многим). У игрока есть команда (много к одному)

Когда бы я ни захотел добавить нового игрока, я бы сделал:

Team team = getTeamFromDbUsingEntityManager (teamId);Player player = новый игрок ();... player.setTeam (команда);entityManager.persist (player);

Обратите внимание, что это не делает team.addPlayer (player);Это означает, что вы не «касаетесь» коллекции.

...