Как указать время ожидания @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 ответа

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

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

Пессимистический тайм-аут блокировки

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

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

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

Для 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.