Какова наилучшая практика для классов сущностей JPA / Hibernate и синхронизации? - PullRequest
2 голосов
/ 08 октября 2008

Похоже, что в большинстве примеров классов объектов-сущностей JPA / Hibernate, которые я видел, нет явной синхронизации. Тем не менее, можно вызывать методы получения / установки этих объектов в контексте построения транзакции. И эти методы можно вызывать из нескольких потоков (хотя, может быть, это необычно и странно).

Похоже, что если он построен в нескольких потоках, то возможны потери изменений состояния объекта, что было бы печально.

Так что, лучше не использовать синхронизацию? Инструментальный код Hibernate позаботился о правильной синхронизации для меня?

Как пример:

@Entity
public class Ninja {
  @Id @GeneratedValue
  private Long id;

  @Column 
  private String name;

  @Column
  private int throwingStars;

  public Ninja() {}
  public int getThrowingStars() { return throwingStars; } 
  public void addThrowingStar() { throwingStars += 1; }
}

Нужна ли методам метания звездочки синхронизация? Я уверен, что не хочу, чтобы мой ниндзя потерял метательные звезды.

Ответы [ 5 ]

3 голосов
/ 17 апреля 2009

По моему мнению, вы НИКОГДА не должны делиться объектами доменов между потоками. На самом деле я обычно разделяю очень мало между потоками, поскольку такие данные должны быть защищены. Я создал несколько больших / высокопроизводительных систем и никогда не нарушал это правило. Если вам нужно распараллелить работу, делайте это, но НЕ делитесь экземплярами объектов домена. Каждый поток должен читать данные из базы данных, работать с ней, изменяя / создавая объекты, а затем фиксируя / откатывая транзакцию. Как правило, вход / выход рабочей области должны быть объектами value / readonly.

2 голосов
/ 08 октября 2008

"И эти методы можно вызывать из нескольких потоков (хотя, может быть, это необычно и странно)."

Я могу говорить ТОЛЬКО в спящем режиме, поскольку у меня нет большого опыта работы с JPA. Объект, для которого вы вызываете set, НЕ всегда является тем же объектом, для которого вы вызываете get. Когда Hibernate загружает объект для вас, он вызывает методы set *, а затем вы (и ваши потоки) вызываете все остальное время.

Опять же, когда вы (т. Е. Ваши потоки записи) изменяете существующий объект и затем сохраняете его снова, вам необходимо защитить доступ к объекту (чтобы другие потоки чтения / записи не читали грязные данные).

1 голос
/ 14 октября 2008

Объект, вероятно, не одинаков для двух потоков. Предположим, что ваши потоки используют фабрику сеансов для доступа к БД, объекты, которые вы получаете из сеанса, должны рассматриваться как «независимые» (я считаю, что hibernate создает «свежие» объекты для каждого get (), если они не находятся в сеансе).

Что касается вопроса о звездах, то же самое происходит, когда два человека выбирают одну и ту же строку из БД, свойства ACID БД гарантируют, что каждая операция является атомарной, поэтому, если вы удалите звезду из ниндзя в потоке t1 и commit , поток t2 будет считывать зафиксированные значения t1.

В качестве альтернативы, вы можете попросить hibernate заблокировать строку соответствующего ниндзя в T1, так что даже если T2 запрашивает строку, ему придется ждать, пока T1 не завершит фиксацию или остановится.

0 голосов
/ 25 марта 2009

Лучшей практикой для вашей проблемы является оптимистическая блокировка:

Из спецификации Java Persistence API (JPA) (глава 3.4.1):

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

Вам необходимо добавить аннотацию @Version для вашего класса и столбец в таблице БД.

0 голосов
/ 18 февраля 2009

JPA / Спящие сущности - это POJO. Hibernate и любой JPA-провайдер не изменяют семантику времени выполнения.

Так что, если у вас возникнут проблемы параллелизма с простым POJO, у вас также будут проблемы с вашей сущностью!

Во всех системах, которые я видел, модель домена не является потоковой, экземпляры сущностей не доступны нескольким потокам.

Однако вы можете одновременно иметь несколько экземпляров одних и тех же объектов. В этом случае синхронизация выполняется через БД. Модели здесь - Оптимистическая и Пессимистическая Блокировка. Hibernate и JPA могут помочь вам в реализации этих шаблонов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...