我有Hibernate的Java EE应用程序。我想实现一个每分钟更新数据库中现有行之一的功能。我有以下课程:
@Singleton
@Startup
public class TimerRunnerImpl implements TimerRunner {
@EJB
private WorkProcessor workProcessor;
private String jobId;
@Timeout
@AccessTimeout(value = 90, unit = TimeUnit.MINUTES)
@TransactionAttribute(value = TransactionAttributeType.NEVER)
public void doProcessing(Timer timer) {
jobId = workProcessor.doWork(jobId);
}
//other methods: startTimer, etc
}
@Stateless
public class WorkProcessorImpl implements WorkProcessor {
@EJB
private MyEntityDao myEntityDao;
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Override
public String doWork(String jobId) {
if (jobId == null) {
MyEntity myEntity = myEntityDao.oldestEntityToProcess();
String uuid = UUID.randomUUID().toString();
myEntity.setJobId(uuid);
myEntityDao.update(myEntity); // this invokes merge()
return uuid;
} else {
// line below can never find entity, although there is one in DB
MyEntity myEntity = myEntityDao.findByJobId(jobId);
myEntity.setSomeProperty("someValue");
// some other updates
myEntityDao.update(myEntity); // this invokes merge()
return jobId;
}
}
}
首次运行的doWork使用作业ID更新MyEntity。这被持久化到数据库中 - 我可以从SQLDeveloper手动查询它。第二次运行始终无法按作业ID查找实体。如果我尝试在调试模式下通过entity_id检索它,则从实体管理器检索的对象具有带有先前值的作业ID。
这不是缓存问题,我已尝试在每次运行时开始逐出所有缓存并且结果相同。
据我了解,事务是围绕workProcessor.doWork(jobId)。我通过这个方法返回时可以看到DB的变化这一事实找到了确认。但是为什么EntityManager会保留我未经修改的对象并在查询时返回它?