Я работаю над пакетом JavaEE для управления некоторыми данными. Пакетный процесс инициализируется, затем вызывает функциональные методы (для элемента управления l oop), и каждые 1000 контролируемых строк я записываю некоторую информацию в базу данных (JPA), чтобы регистрировать возможные дельты.
Если я поставлю @ Транзакционная аннотация по методу процесса в начале, он работает, я нахожу свои дельта-журналы в БД. Но, когда элементы управления занимают больше времени, чем длительность транзакции, они, конечно, откатываются.
Так что (как это рекомендуется по многим темам здесь) я поместил @Transactional в диспетчере персистентности на ближайшем метод регистрации дельт. Он преобразует боб журнала (с дельта-информацией) в сущность, а затем объединяет его (javax.persistence.EntityManager.merge), чтобы создать его в базе данных.
Но, хотя в методе есть @Transactional , У меня ошибка:
The method public abstract java.lang.Object javax.persistence.EntityManager.merge(java.lang.Object) must be called in the context of a transaction.
Кто-то имеет представление о том, что мне не хватает?
Какой-то код:
// package, imports...
@Named("MyBatchlet")
@Dependent
public class MyBatchlet implements Batchlet {
@Inject
private Logger logger;
@Inject
private MyTF MyTF;
@Override
// @Transactional(Transactional.TxType.REQUIRED)
public String process() {
// init parameters
...
// Loop on some blocks of data
try {
for (String data : datas) {
status = MyTF.analyzeData();
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void stop() throws Exception {
}
}
public class MyTF {
@Inject
private Logger logger;
@Inject
private ManagerPersistance managerPersistance;
@SuppressWarnings({ "unchecked", "rawtypes" })
public StatutExecution analyzeData() throws SQLException {
// init report
saveReport(synthesis, null);
// control loop, for ex 100.000 rows
while (...) {
...
if (position % 1000 == 0) {
saveReport(synthesis, details);
}
}
}
@Transactional(Transactional.TxType.REQUIRED)
public void saveReport(MySynthesis synthesis, List<MyDetail> details) {
if (synthesis!=null) managerPersistance.saveSynthesis(new MySynthesisEntity (synthesis));
if (details!=null) {
for (MyDetail detail : details) {
managerPersistance.saveDetail(new MyDetailEntity (detail));
}
}
}
// ...
}
public class ManagerPersistance {
@Inject
private Logger logger;
@Inject
@MyDatabase
EntityManager entityManager;
public void saveSynthesis(MySynthesisEntity synthesis) {
entityManager.merge(synthesis);
entityManager.flush();
}
public void saveDetail(MyDetailEntity detail) {
entityManager.merge(detail);
entityManager.flush();
}
}