简体   繁体   English

@Transactional在方法级别不起作用

[英]@Transactional does not work on method level

I have a question about Spring 3.2.3 @Transactional annotation. 我对Spring 3.2.3 @Transactional注解有疑问。 My Service class looks like this: 我的服务类如下所示:

@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) {
 ...
}
}

All works perfectly if I call persist() method. 如果我调用persist()方法,所有方法都可以正常工作。 But if I comment out @Transactional at class level - transaction does not start. 但是,如果我在类级别将@Transactional注释掉-事务将不会启动。 Could anybody tell me why Spring could ignore @Transactional on methol-level only? 谁能告诉我为什么Spring只能在methol级忽略@Transactional吗?

You cannot call persist() from processDisclosureData() because it belongs to the same class and it will bypass transactional proxy created by Spring for InventoryDisclosureBO. 您不能从processDisclosureData()调用persist(),因为它属于同一类,并且它将绕过Spring为InventoryDisclosureBO创建的事务代理。 You should call it from other beans to make @Transactional annotations work. 您应该从其他bean调用它以使@Transactional批注起作用。 When Spring injects a reference to InventoryDisclosureBO bean to other beans it actually injects a reference to InventoryDisclosureBOProxy which contains transactional logic, eg 当Spring将对InventoryDisclosureBO Bean的引用注入其他Bean时,它实际上将对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
      }
...

This is related to how spring generates the transactional proxies. 这与spring如何生成事务代理有关。

In the case where you have @Transactional at the class level, when you call InventoryDisclosureBO.processDisclosureData() , in fact, you're calling a Spring proxy that starts the transaction, and then calls the real implementation. 实际上,在类级别具有@Transactional的情况下,实际上,当您调用InventoryDisclosureBO.processDisclosureData() ,您是在调用Spring代理来启动事务,然后调用实际实现。

If you only have @Transaction in persis(), spring doesn't start a transaction when you call InventoryDisclosureBO.processDisclosureData() , and then it cannot detect that you've called InventoryDisclosureBO.persist() 如果在persis()中仅具有@Transaction,则在调用InventoryDisclosureBO.processDisclosureData()时spring不会启动事务,因此它无法检测到您已调用InventoryDisclosureBO.persist()

So Spring basically ignores the annotation on persist , because it cannot add the transactional proxy. 因此,Spring基本上会忽略对persist的注释,因为它无法添加事务代理。

As a rule of thumb, the @Transactional annotation should be on a public method, and hopefully quite high in the call hierarchy (otherwise each persist would end up creating a new transaction) 根据经验,@ Transactional批注应位于公共方法上,并希望在调用层次结构中处于较高级别(否则,每个持久化将最终创建一个新事务)

You might find more information on this other SO question: Method Interceptor on private methods (any non-public methods behave in the same way) 您可能会找到有关此其他SO问题的更多信息: 私有方法的方法拦截器 (任何非公共方法的行为均相同)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM