2012-08-14 194 views
1

我使用spring和hibernate。我正在使用spring進行事務管理。我有下課。春季交易管理問題?

@Service 
@Transactional(readOnly = true) 
public class Sample implements SampleInterface{ 

@Override 
public List<Some> getData(){ 

//gets data after that it updates something 

setStatus(someId); 

} 

@Override 
@Transactional 
public void setStatus(Long someId){ 

//sets status 

} 

} 

如果我不保留@Transactional getData()然後我得到異常下面。

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode 

如果我保留@Transactional getData(),那麼它將正確保存。這裏有什麼問題?任何我有@Transactional爲setStatus()。我還需要爲getData()保留@Transactional,因爲它正在調用將設置狀態的公共方法?

謝謝!

回答

5

這個問題有點複雜,是由 內部getData()造成的。當你從外部調用getData()時,實際上你正在調用Spring框架爲你創建的Java代理。此代理應用事務行爲(啓動只讀事務)並委託給您的實際服務類。這工作正常。

但是,當您撥打setStatus()時,您將繞過事務代理並直接調用您的服務。換句話說,對setStatus()的請求不被攔截,並且@Transactional被忽略

有沒有簡單的方法來處理這個問題,也有同樣的問題。調用同一個類中的公共方法時,您必須格外小心。

+0

感謝您的回覆。如果我保留@Transactional getData(),那麼我的問題就解決了。這是不錯的做法嗎? – user1016403 2012-08-14 11:17:59

+0

@ user1016403:這不是最好的方法,但我沒有找到更好的方法。你*可以*提取'setStatus()',但它不會解決你的特定問題。 – 2012-08-14 11:32:25

+0

感謝您的回覆! – user1016403 2012-08-14 11:46:40

1

當你(在方法不@Transactional)調用的getData春天將開始一個只讀的事務作爲是你的類的默認值,當getData調用時,setStatus Spring將使用現有的只有rad的事務,而不是創建一個新的。這就是你獲得例外的原因。

缺省事務傳播是PROPAGATION REQUIRED。閱讀更多關於主題http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation

+0

恕我直言,在這種特殊情況下'@Transactional'註釋被完全忽略。即使使用REQUIRES_NEW傳播也會產生相同的錯誤。 – 2012-08-14 11:17:51