Java EE 7 - Как начать транзакцию из контейнера? - PullRequest
0 голосов
/ 16 апреля 2019

Я использую Java EE 7 + GlassFish и мне нужно выполнить некоторые операции с несколькими сущностями JPA из bean-компонента без сохранения состояния.

@Stateless
public class JobRunner 
{
    public void do()
    {
            for (Entity entity:facade.findAll()) 
            {
                ///do some work against entity
            }
    }
}

Этот компонент JobRunner внедряется в сервлет, и я вызываюМетод do () из веб-интерфейса.

Проблема заключается в том, что все сущности меняются в одной транзакции, поэтому при сбое все откатывается, что нежелательно.Есть ли способ запустить и закрыть новую транзакцию для каждой сущности (то есть для каждой итерации цикла)?

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

Может быть, JMS поможет?Если я реализую исполнителя в качестве прослушивателя сообщений и буду отправлять сообщение для каждой сущности, начнется ли новая транзакция для каждой?

@Stateless
public class JobRunner 
{
    public void do()
    {
            for (Entity entity:facade.findAll()) 
            {
                sendMessageToRealDoer(entity);
            }
    }
}

1 Ответ

2 голосов
/ 16 апреля 2019

Создание другого компонента с указанием @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) на уровне метода или компонента:

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
public class JobWork {
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void doWork(Entity entity) {
        // do what you would do in the loop with the Entity
        // this runs in a new transaction
    }
}

Хотелось бы вам сказать, что вам нужно всего лишь аннотировать метод того же компонента (JobRunner) и просто вызывать его. Это невозможно (EDIT) без обходных путей - проверьте комментарий из Steve C (/ EDIT), потому что при вызове методов объекта this в EJB и бобах CDI перехватчики не вызываются. Транзакции осуществляются с перехватчиками в обоих случаях.

Некоторые заметки:

  • Если ожидается, что общая продолжительность операций в цикле будет большой, вы получите тайм-аут во внешней транзакции , которая неявно запускается для JobRunner EJB без сохранения состояния. Вы захотите принять меры, чтобы «внешняя» транзакция не была запущена.
  • Отправка данных в очередь тоже будет работать; но очереди будут обрабатывать их асинхронно, что означает, что выполнение вернется к сервлету, вызывающему JobRunner.do(), скорее всего, до того, как все элементы будут обработаны.
...