2013-09-03 2 views
3

У меня есть вопрос о Spring 3.2.3 @Transactional аннотация. Мой класс Service выглядит следующим образом:@Transactional не работает на уровне метода

@Service @Transactional 
class InventoryDisclosureBO { 

@Autowired InventoryDisclosureDAO inventoryDisclosureDAO; 

private static final Logger log = LoggerFactory.getLogger(InventoryDisclosureBO.class); 

public void processDisclosureData(InventoryDisclosureStatus data){ 
    validate(data); 
    persist(data); 
} 

@Transactional(propagation = REQUIRES_NEW) 
void persist(InventoryDisclosureStatus data) { 
    inventoryDisclosureDAO.setAllInvalid(data.getUnit()); 
    inventoryDisclosureDAO.insert(data); 
} 

void validate(InventoryDisclosureStatus data) { 
... 
} 
} 

Все отлично работает, если я позвоню упорствовать() метод. Но если я прокомментирую @Transactional на уровне класса - транзакция не начинается. Может ли кто-нибудь сказать мне, почему Spring может игнорировать @Transactional только на уровне метола?

ответ

4

Вы не можете вызвать persist() из processDisclosureData(), потому что он принадлежит к одному классу и будет обходить транзакционный прокси, созданный Spring для InventoryDisclosureBO. Вы должны называть это из других bean-компонентов, чтобы сделать аннотации @Transactional. Когда весна впрыскивает ссылку на InventoryDisclosureBO фасоли других бобов он фактически вводит ссылку на InventoryDisclosureBOProxy, который содержит транзакционной логики, например

class Bean2 { 

     @Autowire 
     private InventoryDisclosureBO idbo; <-- Spring will inject a proxy here 

     public void persist(InventoryDisclosureStatus data) { 
      idbo.persist(data);  <-- now it will work via proxy 
     } 
... 
+0

Спасибо, Евгений, это делает смысл! Если я ставил @Transactional только на processDisclosureData(), он работает отлично. – never

+0

1) можете ли вы, пожалуйста, увеличить его бит в ответе? Persist() будет обходить транзакционный прокси, созданный Spring для InventoryDisclosureBO « –

+0

2) idbo.persist (data); <- теперь он будет работать через прокси-сервер, это потому, что мы вызываем метод persist непосредственно извне класса? если это так, то как это имеет значение? –

3

Это связано с тем, как пружина формирует транзакционные прокси.

В случае, когда у вас есть @Transactional на уровне класса, когда вы вызываете InventoryDisclosureBO.processDisclosureData(), на самом деле вы вызываете прокси-сервер Spring, который запускает транзакцию, а затем вызывает реальную реализацию.

Если у вас есть только @Transaction в Персии(), пружина не начать транзакцию, когда вы звоните InventoryDisclosureBO.processDisclosureData(), и тогда он не может определить, что вы назвали InventoryDisclosureBO.persist()

Так весной в основном игнорирует аннотацию persist , поскольку он не может добавить транзакционный прокси.

Как правило, аннотация @Transactional должна быть общедоступным метод, и, надеюсь, довольно высоко в иерархии вызовов (в противном случае каждый упорствовать бы в конечном итоге создать новую транзакцию)

Вы можете найти более подробную информацию на этот другой вопрос SO: Method Interceptor on private methods (любые непубличные методы ведут себя одинаково)

+0

, если @Transactional is применяется на уровне класса, только тогда весна порождает прокси-транзакцию? –

+0

, если @Transactional не применяется на уровне класса и методе processDisclosureData, то почему он не может обнаружить, что вы вызвали InventoryDisclosureBO.persist()? –

Смежные вопросы