2017-02-03 174 views
0

即時通訊使用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綁定到線程。 謝謝。

+0

我相信'@ scheduled'註釋在spring'@ transactional'註釋中不能很好地發揮作用。 Spring從這些類中構建代理,並且可能無法在同一個方法上處理兩個註釋。 – user152468

+0

雖然 – Juan

+0

我沒有使用@transactional註釋,但如果使用@RestController或類似的東西,它可能是隱含的。 – user152468

回答

0

如果從控制器使用,您可能有一個開放實體管理器在視圖中的模式,在您的請求正在運行並生成報告的整個時間段內打開EntityManager

從您的計劃方法運行時,您可能不會將您使用的EntityManager綁定到當前線程,因此在您的方法運行的整個過程中它都不會打開並生成報告。這意味着它會按需打開(即在你的DAO代碼中),但會在從該方法返回時關閉,導致實體分離。

嘗試使用TransactionSynchronisationManagerbindResource函數,它提供了一個EntityManagerHolder的實例。基本上OpenEntityManagerInViewInterceptor是做什麼的,你可以查看源代碼,並創建一個類似的方法,它在89行左右。