我正在处理JavaEE批处理,以控制一些数据。 Batchlet进程初始化,然后调用功能方法(用于控制循环),每控制1000行,我就在数据库(JPA)中写入一些信息,以便记录可能的增量。
如果我在一开始将@Transactional批注放在处理方法上,它将起作用,我会在db中找到增量日志。 但是,当控件花费的时间超过事务处理时间时,它就会回滚。
因此(在这里似乎有很多主题建议),我在持久性管理器中将@Transactional放在最接近的增量日志记录方法中。它将日志bean(带有增量信息)转换为一个实体,然后将其合并(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();
}
}