JPA: блокировка зависимых объектов (eclipselink) - PullRequest
0 голосов
/ 30 июня 2011

У меня простые отношения ко многим в JPA.для обсуждения предположим, что мои сущности - это Персона и Телефон, где Персона может иметь много Телефонов (номеров).

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

поэтому в моем коде я делаю что-то вроде

            em.getTransaction().begin();
            Person p = em.find(Person.class, id, LockModeType.PESSIMISTIC_WRITE);
            ...

и аналогично для телефона

            em.getTransaction().begin();
            Phone ph = em.find(Phone.class, id, LockModeType.PESSIMISTIC_WRITE);
            ...

обратите внимание, что в транзакции Person зависимый объект Phone может быть обновлен, и наоборот.вариант использования - это флаг lastModified.Обновление телефона обновляет отметку времени lastModified в Person, и, наоборот, обновление отметки времени lastModified в Person обновляет флаг lastModified в Phone (это делается через прослушиватели сущностей).Я понимаю, что сценарий использования немного надуман, но попробуйте проигнорировать это.

приведенный выше код приводит к мертвой блокировке.

INFO: [EL Warning]: 2011-06-30 08:41:52.65--ServerSession(122902)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLTransactionRollbackException: A lock could not be obtained within the time requested
Error Code: 30000

В настоящее время моя гипотеза заключается в том, что транзакция Person захватывает блокировку для Person A, а затем пытается получить блокировку для Phone 1. В то же время транзакция Phone захватывает блокировку для Phone.1, побеждая транзакцию Person, затем пытается получить блокировку для тупика Person A.

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

есть мысли?

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

1 Ответ

2 голосов
/ 30 июня 2011

Мне кажется очень странным, что вам одновременно

  • нужны пессимистичные блокировки (что, по-видимому, означает, что вы действительно не хотите, чтобы две транзакции обновляли людей / телефоны одновременновремя)
  • готовы пожертвовать согласованностью данных, выполнив одну операцию в двух отдельных транзакциях

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

...