我对Spring 3.2.3 @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) {
...
}
}
如果我调用persist()方法,那么一切都很完美。但是如果我在课堂级别注释掉@Transactional - 事务没有开始。 有人能告诉我为什么Spring只能在甲醇水平上忽略@Transactional吗?
答案 0 :(得分:5)
您无法从processDisclosureData()调用persist(),因为它属于同一个类,它将绕过Spring为InventoryDisclosureBO创建的事务代理。您应该从其他bean调用它以使@Transactional注释工作。当Spring向其他bean注入InventoryDisclosureBO 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
}
...
答案 1 :(得分:3)
这与spring如何生成事务代理有关。
如果您在类级别拥有@Transactional,那么当您调用InventoryDisclosureBO.processDisclosureData()
时,实际上您正在调用启动事务的Spring代理,然后调用实际实现。
如果你在persis()中只有@Transaction,那么当你调用InventoryDisclosureBO.processDisclosureData()
时,spring不会启动事务,然后它无法检测到你调用了InventoryDisclosureBO.persist()
所以Spring基本上忽略了persist
上的注释,因为它无法添加事务代理。
根据经验,@ Transactal注释应该在公共方法上,并且希望在调用层次结构中相当高(否则每个持久化将最终创建一个新事务)
您可能会发现有关此其他问题的更多信息:Method Interceptor on private methods(任何非公开方法的行为方式相同)