2016-08-10 2 views
0

У меня есть два объекта JPA, которые связаны друг с другом. Человек может быть членом или группой. Группа может иметь ноль или более членов.Как обрабатывать отношения JPA OneToMany в многопоточной среде

@Entity 
public class PersonEntity { 

    @ManyToOne 
    @JoinColumn(name = "GROUP_ID") 
    private GroupEntity group; 
} 

@Entity 
public class GroupEntity { 

    @OneToMany(mappedBy = "group", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }) 
    private Collection<PersonEntity> persons; 

} 

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

  1. персоны и personB принадлежат группа1
  2. Резьба1 удаляет персона из group1
  3. thread2 удаляет personB из group1
  4. thread1 делают некоторые постобработки с personB
  5. thread2 делают некоторые пост-обработку с персонами

Я знаю, что могу обернуть это все в синхронизированном блоке, но это не помогло бы мне, если приложение работающих на нескольких компьютерах, которые совместно используют базу данных.

Как JPA может знать, что коллекция на GroupEntity была изменена другим потоком?

+3

Вообще-то его дело бережно связано с транзакцией базы данных. Может быть, вы должны изучить это. Какова среда, в которой вы используете код? Сервер приложений или автономный проект? Или вы хотите, чтобы объекты Java сохраняли синхронизацию для каждого потока? –

+0

Удаление производится в транзакции. Постобработка выполняется после фиксации. – TomVW

ответ

1

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

Используйте стратегию блокировки базы данных для обработки одновременных обновлений к объекту

Вместо этого, вы хотите, чтобы рассмотреть запирающий стратегию базы данных и использование транзакций базы данных. JPA поддерживает как optimistic and pessimistic locking. Обычно вы можете достичь лучшей производительности с оптимистичной блокировкой, которая использует поле версии для отслеживания обновлений для каждого из ваших объектов.

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

Используйте таблицы объединения для устранения разногласий между изменениями в член группы и лица атрибуты

Предполагая, что удаление человека из группы не удаляет человек, может быть другой способ, чтобы удалить раздор в этом сценарии. Как правило, в отношении «один ко многим» строка «Личность» будет содержать ссылку на идентификатор группы, к которой она принадлежит. Это заставляет Thread 1 и Thread 2 конкурировать за обновления строки Person. Вместо этого, вы можете переместить отношения один-ко-многим в отдельную таблицу соединения, так что резьба 1 может удалить персонами из Group1 в то же время, что Резьба2 делает последующую обработку с персонами

О синхронизации коллекции отношений между JVM,

JPA реализует несколько моделей настойчивости Martin Fowler подробнее в Patterns of Enterprise Application Architecture. Один из этих шаблонов - Unit of Work, который отслеживает изменения, сделанные во время «сеанса». Я считаю, что Thread1 и Thread2 работают в отдельных единицах работы, и поэтому им следует избегать попытки синхронизации своих кэшей в памяти данных, полученных из базы данных.Вместо этого Thread1 получит изменения Thread2 при следующем запросе базы данных. Пусть в базе данных возникает проблема синхронизации состояния через распределенную систему.

Если вам необходимо управлять распределенными транзакциями, просмотрите JTA; однако я не уверен, какие поставщики JPA могут распространять состояние памяти своей единицы работы в рамках распределенной транзакции. Это ситуация, которую я постарался бы избежать, а не ручку

+0

Я не уверен, что это решит мою проблему. Версия в группе не изменяется, когда человек удаляется. Кроме того, исключение блокировки неудобно, мне пришлось бы выполнить пост-обработку в цикле, пока не будет выбрано исключение. – TomVW

+0

Правильно, версия группы не меняется. Не должно быть никаких претензий к изменениям в группе: удаление строк Person A и Person B из таблицы Person совсем не влияет на таблицу групп. Если вы хотите избежать оптимистических исключений блокировки из-за конкуренции, вызванной одновременными обновлениями для Лица, вы можете попробовать пессимистичную блокировку, которая гарантирует, что Лицо, которое вы прочитали, будет таким же, когда вы его обновите. – jdgilday

+0

может быть другой способ, я обновил свой ответ – jdgilday

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