Как указать время ожидания @lock в spring запросе данных jpa?

Как указать @lock таймаут для запроса. Я использую oracle 11g, я надеюсь, что смогу использовать что-то вроде 'select id from table where id = ?1 for update wait 5'.

Я определил такой метод,

@Lock(LockModeType.PESSIMISTIC_WRITE)
Stock findById(String id);

Кажется, замок навсегда. i установить javax.persistence.lock.timeout=0 в LocalContainerEntityManagerFactoryBean.jpaProperties, но не выполнить.

3 ответа

Чтобы заблокировать объекты пессимистично, установите режим блокировки на <code>PESSIMISTIC_READ</code>, <code>PESSIMISTIC_WRITE</code> или <code>PESSIMISTIC_FORCE_INCREMENT</code>.

Если пессимистическая блокировка не может быть получена, но отказ блокировки не приводит к откату транзакции, a <code>LockTimeoutException</code>выброшены.

<a href="http://docs.oracle.com/javaee/6/tutorial/doc/gkjiu.html" rel="nofollow noreferrer" target="_blank"><span> Пессимистический тайм-аут блокировки</span></a>

Продолжительность времени в миллисекундах, которую провайдер персистентности должен подождите, чтобы получить блокировку в таблицах базы данных, можно указать, используя свойство javax.persistence.lock.timeout. Если время, необходимое для получить блокировку, превышающую значение этого свойства, <code>LockTimeoutException</code> будет выбрано, но текущая транзакция не будет отмечен для отката. <span> Если для этого свойства установлено значение 0, поставщик устойчивости должен бросить a <code>LockTimeoutException</code>, если он не может сразу получить блокировку.</span>

Если <code>javax.persistence.lock.timeout</code> задано в нескольких местах, значение будет определено в следующем порядке:

<ul> <li> Аргумент для одного из <code>EntityManager</code> или <code>Query methods</code>.</li> <li> Настройка в аннотации <code>@NamedQuery</code>.</li> <li> Аргумент метода <code>Persistence.createEntityManagerFactory</code>.</li> <li> Значение в дескрипторе развертывания <code>persistence.xml</code>.</li> </ul>

Для Spring данных 1.6 или выше

@Lock поддерживается по методам CRUD по версии 1.6 из Spring Data JPA (на самом деле уже существует milestone доступно). Подробнее см. .

С этой версией вы просто объявляете следующее:

interface WidgetRepository extends Repository<widget, long=""> {
 @Lock(LockModeType.PESSIMISTIC_WRITE)
 Widget findOne(Long id);
}
</widget,>

Это приведет к тому, что часть реализации CRUD прокси-сервера репозитория будет использовать сконфигурированный метод LockModeType для вызова find(…) на EntityManager.

С другой стороны,

Для предыдущей версии Spring Данные 1.6

Аннотации Spring Пессимистические данные @Lock применяются только (как вы указали) к запросам. Я не знаю, какие аннотации могут повлиять на всю транзакцию. Вы можете либо создать метод findByOnePessimistic, который вызывает findByOne с пессимистической блокировкой, либо вы можете изменить findByOne, чтобы всегда получать пессимистическую блокировку.

Если вы хотите реализовать свое собственное решение, вы, вероятно, могли бы. Под капотом аннотация @Lock обрабатывается LockModePopulatingMethodIntercceptor, которая выполняет следующие действия:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

Вы можете создать некоторый статический менеджер блокировки, который имеет переменную-член ThreadLocal, а затем иметь аспект, обернутый вокруг каждого метода в каждом репозитории, который вызвал bindResource с режимом блокировки, установленным в ThreadLocal. Это позволит вам установить режим блокировки по каждому потоку. Затем вы можете создать свою собственную аннотацию @MethodLockMode, которая будет обертывать метод в аспекте, который устанавливает режим блокировки, зависящий от потока, перед запуском метода и очищает его после запуска метода.

Ссылка на ресурс:

Различные примеры пессимистического времени блокировки

Установка пессимистической блокировки

Объект сущности может быть заблокирован явно методом блокировки:

em.lock(employee, LockModeType.PESSIMISTIC_WRITE);

Первый аргумент - объект объекта. Второй аргумент - запрошенный режим блокировки.

A TransactionRequiredException вызывается, если нет активной транзакции при вызове блокировки, потому что для явной блокировки требуется активная транзакция.

A LockTimeoutException выдается, если запрошенная пессимистическая блокировка не может быть предоставлена:

  • A PESSIMISTIC_READ запрос блокировки завершается с ошибкой, если другой пользователь (который представленный другим экземпляром EntityManager) в настоящее время содержит PESSIMISTIC_WRITE заблокировать этот объект базы данных.
  • Ошибка запроса PESSIMISTIC_WRITE блокировки, если другой пользователь в настоящее время содержит либо блокировку PESSIMISTIC_WRITE, либо блокировку PESSIMISTIC_READ этот объект базы данных.

Настройка подсказки (Области)

Подсказки запроса могут быть установлены в следующих областях (от глобального к локальному):

Для всей единицы измерения продолжительности - с использованием свойства persistence.xml:

<properties>
 </properties>

Для EntityManagerFactory - с помощью метода createEntityManagerFacotory:

Map<string,object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
 Persistence.createEntityManagerFactory("pu", properties);
</string,object>

Для EntityManager - с помощью метода createEntityManager:

Map<string,object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
</string,object>

или используя метод setProperty:

em.setProperty("javax.persistence.query.timeout", 6000);

Для определения named query - с помощью элемента hints:

@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
 hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})

Для конкретного выполнения запроса - с помощью метода setHint (до выполнения запроса):

query.setHint("javax.persistence.query.timeout", 8000);

Ссылка на ресурс:


Вы можете использовать @QueryHints в Spring Данные:

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")})
Stock findById(String id)


Для Spring данных 1.6 или выше мы можем использовать аннотацию @Lock, предоставленную Spring данными jpa.

Кроме того, время блокировки также может быть установлено с помощью @QueryHints. Первоначально не было поддержки аннотаций подсказок запроса в методах CRUD по умолчанию, но оно было доступно после исправления 1.6M1. https://jira.spring.io/browse/DATAJPA-173

Ниже приведен пример пессимистической блокировки с типом режима PESSIMISTIC_WRITE, который является исключительной блокировкой.

@Lock(LockModeType.PESSIMISTIC_WRITE) 
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 
Customer findByCustomerId(Long customerId);

licensed under cc by-sa 3.0 with attribution.