2014-01-28 102 views
3

我的服務類。春季交易管理Propagation.REQUIRES_NEW不起作用

@Service 
@Transactional(value = "transactionManager", readOnly = true, propagation = Propagation.REQUIRED) 
public class DeviceServiceImpl{ 

@Transactional(readOnly = false) 
public void blockAllDevices(){ 

    createSmsDeviceBlock(); 

} 


public void createSmsDeviceBlock(){ 

    addToLogTables(); 

    smsService.sendSms(); 
} 


@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW) 
public void addToLogTables(){ 
     try { 
      //save object with DAO methods... 
     } catch (Exception e) { 
      throw new ServiceException(ServiceException.PROCESSING_FAILED, e.getMessage(), e); 
     } 
} 

}

從我的控制器,服務方法blockAllDevices()獲取調用。 addToLogTables()方法被標記爲Propergation.REQUIRED_NEW,但問題在於addToLogTables()方法新事務沒有被創建並且現有事務正在使用。

我想要做的事情是,在addToLogTables交易()方法應該提交之前執行smsService.sendSms()方法。

我在這裏的問題,如果交易未能提交,在方法addToLogTables()方法,它不應該執行smsService.sendSms()方法。

回答

7

這不是一個Propagation.REQUIRES_NEW問題。 @Transactional代理如何工作是個問題。

當Spring代理註釋爲@Transactional的bean時,它基本上將其包裝在代理對象中並在打開事務後委託給它。當委託調用返回時,代理會提交或回退事務。

例如,你的bean是

@Autowired 
private DeviceServiceImpl deviceService; 

春天其實是要注入的包裝代理。

所以,當你做

deviceService.blockAllDevices(); 

要調用其上有事務行爲的代理方法。然而,在blockAllDevices(),你正在做

createSmsDeviceBlock(); 

這實際上是

this.createSmsDeviceBlock(); 

其中this指的是實際的對象,而不是代理,所以沒有交易行爲。

這在documentation進一步解釋。

你必須返工你的設計。

+0

我可以理解這一點,但有沒有其他辦法可以做到這一點...? 這就是在同一個內部創建新的交易。 –

+0

您必須從外部或編輯器進行調用,以便事務性方法位於您注入其中的某個其他bean上。 –

+1

您可以使用基於AspectJ的事務管理和加載時間或編譯時編織和彈簧方面,這允許您進行事務性自調用,私有事務方法等。查看Spring文檔以獲取更多信息。 – Jukka