@Transactional для метода, но всегда ошибка «должна вызываться в контексте транзакции» - PullRequest
0 голосов
/ 10 марта 2020

Я работаю над пакетом 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();
    }
}
...