Объект пакетного обновления JPA/Eclipselink с низкой производительностью при изменении отношений ManyToOne

У меня проблема с пакетной записью в 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 * from card where cardholder.id =?), поэтому для 15000 записей я получил 15000 операторов select. Лучше, чем выше, но все равно очень-очень медленно.

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


person Andoko    schedule 10.12.2010    source источник
comment
Можете ли вы также опубликовать код EntityManager? Выдаете ли вы em.flush() в любой момент?   -  person Gordon Yorke    schedule 13.12.2010


Ответы (2)


Каковы все отношения в карте и держателе карты?

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

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

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

person James    schedule 23.03.2011

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

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

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

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

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

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

person Albert Gan    schedule 22.03.2011