传播.REQUIRES_NEW似乎不起作用

使用Spring(MVC,Batch和persistence)我定义了以下接口:

public interface JobStatusService { @Transactional(readOnly = false) @Modifying JobStatus save(JobStatus status); @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) Optional get(ResultsIdentifier identifier); } 

请注意REQUIRES_NEW因为它是在破碎的方法上。

该接口实现于:

 @Override public JobStatus save(JobStatus status) { if (status.getUserId() == null) { status.setUserId(userService.getCurrentUser()); } status.setLastUpdateTime(new Date()); return repository.save(status); } @Override public Optional get(ResultsIdentifier identifier) { return repository.findByJobIdentifier(identifier); } 

其中repository是JPA存储库,其中包含以下内容:

 public interface JobStatusRepository extends Repository { JobStatus save(JobStatus status); Optional findByJobIdentifier(ResultsIdentifier id); } 

ResultsIdentifier是字符串代码和ID号的简单复合ID类。

在其他地方,我有一个批处理Writer通过将JobStatus写入存储库来完成,以及一个Web Controller类,它运行一个包含对作业状态服务的查询的循环。 save()操作似乎正确执行,并且get()操作第一次正常工作。

但是,如果循环的第一次运行调用get()并且JobStatus不是“完成”,那么在所有后续运行中它仍然不是“完成”。 事实上,同样的确切对象是从Hibernate(这是我的底层持久性工具)回来的。 发生的事情是SessionImpl / StatefulPersistenceContext中的会话缓存保留了它的副本并始终返回而不是进行真正的数据库查询。 所以,我想, propagation = Propagation.REQUIRES_NEW应该总是启动一个新的事务/会话,对吧? 但是,无论我是否在注释中包含它,都会再次出现同样的问题。

会话和交易的生命周期在这里不是一致的吗? 如果没有,我怎么能告诉Spring我想开始一个新的会话 ? 我试图避免更改我的XML配置以将Hibernate会话工厂推入JobStatusService实现并手动clear()它,因为系统的其他任何部分都没有直接看到Hibernate。

我也很高兴听到有关调试会话相关内容的任何建议,因为在我的代码中它只是一个神奇的注释。

我最终通过在特定实体定义上设置fetch到EAGER来“解决”这个问题。 这似乎不应该起作用,所以我提出这个问题来询问可能发生的事情。