Как управлять транзакциями с помощью JAX-RS, Spring и JPA

Я использую JAX-RS, чтобы предоставить основанный на HTTP интерфейс для управления моделью данных. Модель данных хранится в базе данных и взаимодействует с ней через JPA.

Это позволяет мне модифицировать интерфейс модели данных, чтобы он подходил для клиентов REST, и в основном работает достаточно хорошо. Однако я не уверен, как справиться со сценарием, когда метод, предоставляемый ресурсом JAX-RS, требует транзакции, которая влияет на шаблон JPA get, update, commit-on-tx-end, потому что есть только упаковка транзакции операция get, поэтому обновление никогда не фиксируется. Я вижу ту же проблему, если для одной операции REST требуется несколько операций JPA.

Поскольку я использую поддержку транзакций Spring, очевидно, что нужно применить @Transactional к этим методам в ресурсах JAX-RS. Однако для того, чтобы это работало, Spring должен управлять жизненным циклом ресурсов JAX-RS, а в примерах использования, о которых я знаю, ресурсы создаются с помощью `new', когда это необходимо, что в любом случае заставляет меня немного нервничать.

Я могу придумать следующие решения:

  1. обновить мои методы JPA, чтобы обеспечить управляемую транзакциями версию всего, что я хочу сделать из моего интерфейса REST атомарно. Должен работать, удерживает транзакции за пределами уровня JAX-RS, но предотвращает шаблон получения, обновления, фиксации в конце передачи и означает, что мне нужно создать очень гранулированный интерфейс JPA.
  2. Внедрить объекты ресурсов; но они, как правило, сохраняют состояние и содержат по крайней мере идентификатор объекта, с которым взаимодействуют.
  3. Откажитесь от иерархии ресурсов и внедрите в корень большие суперресурсы без сохранения состояния, которые управляют всей иерархией из этого корня; не связные, большие сервисы
  4. Имеют иерархию внедрённых вспомогательных объектов без сохранения состояния, поддерживающих транзакции, которые «затеняют» фактические ресурсы; ресурсы создаются и удерживают состояние, но делегируют вызовы методов вспомогательным объектам.

У кого-нибудь есть предложения? Вполне возможно, что я где-то упустил какой-то ключевой момент.


Обновление. Чтобы обойти отсутствие транзакций в потоке получения, обновления, фиксации при закрытии транзакций, я могу открыть метод слияния (объекта) EntityManager и вызвать его вручную. Хотя это не аккуратно и не решает большую проблему.


Обновление 2 @skaffman Пример кода: На сервисном уровне JPA внедрены, аннотации работают

public class MyEntityJPAService {
...
@Transactional(readOnly=true) // do in transaction
public MyEntity getMyEntity(final String id) {
    return em.find(MyEntity.class, id);
}

В ресурсе JAX-RS, созданном новым, нет транзакций

public class MyEntityResource {
...
private MyEntityJPAService jpa;
...
@Transactional // not injected so not effective
public void updateMyEntity(final String id, final MyEntityRepresentation rep) {
    MyEntity entity = jpa.getMyEntity(id);
    MyEntity.setSomeField(rep.getSomeField());
    // no transaction commit, change not saved...
}
6
задан brabster 7 March 2012 в 13:52
поделиться