(春季)JPA /休眠奇怪的行为
即时通讯使用spring开发一个简单的休息应用程序。(春季)JPA /休眠奇怪的行为
我想实现一个使用Spring的@Scheduled注释周期性运行的方法。 我有一个方法从外部api获取数据并将其存储到数据库(Spring Jpa Repositories,扩展CrudRepositry)。我拥有的实体是公司和报告(公司有许多报告)。
遇到的问题IM是这样的:
要开始我打电话从控制器更新方法(简单的测试),但现在我想从我的调度类调用它,所以它执行自身。但是,当我移动代码(不修改的话),并从shceduler其称为我得到这个异常:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: Models.Company; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: Models.Company
当我打电话从控制器的方法,这并没有发生,我不知道为什么它现在。
这是使用在这两种情况下的代码IM:
ReportsManager reportsManager = new ReportsManager();
reportsManager.updateReports(resultRepository, companyRepository.findAll());
里面的updateReports方法我做这样的事情:
List<BasicReport> resultsList = new ArrayList<>();
遍历公司的名单和创建报表的对象:
BasicReport currentResult = new BasicReport();
currentResult.setReportName(request.getReportName());
currentResult.setCompany(request.getCompany());
resultsList.add(currentResult);
然后我就保存列表其他地方:
repository.save(currentResults);
werid的事情是,我在这两种情况下使用EXACT相同的代码,并得到不同的结果。 任何想法? 谢谢
编辑:在阅读@ user152468评论和@Dries S我现在增加了一个@Transactional注释到我的调度类和它的工作奇迹。 我猜@transactinal批注将EntityManager绑定到线程。 谢谢。
如果从控制器使用,您可能有一个开放实体管理器在视图中的模式,在您的请求正在运行并生成报告的整个时间段内打开EntityManager
。
从您的计划方法运行时,您可能不会将您使用的EntityManager
绑定到当前线程,因此在您的方法运行的整个过程中它都不会打开并生成报告。这意味着它会按需打开(即在你的DAO代码中),但会在从该方法返回时关闭,导致实体分离。
尝试使用TransactionSynchronisationManagerbindResource
函数,它提供了一个EntityManagerHolder的实例。基本上OpenEntityManagerInViewInterceptor是做什么的,你可以查看源代码,并创建一个类似的方法,它在89行左右。
我相信'@ scheduled'注释在spring'@ transactional'注释中不能很好地发挥作用。 Spring从这些类中构建代理,并且可能无法在同一个方法上处理两个注释。 – user152468
虽然 – Juan
我没有使用@transactional注释,但如果使用@RestController或类似的东西,它可能是隐含的。 – user152468