为什么 Spring Bean 自调用在这里为事务工作

Why Spring Bean Self Invocation is working here for Transaction

环境:

Tomcat 6

Spring 4

休眠 4

Spring MVC

代码:

我有下面的服务层 class :

public interface AbhisheskService {
    public List<AbhishekDTO> findByMatchingCriteria(AbhishekDetailsSearchDTO searchDto);

}

@Service("abhishekService")
public class AbhishekServiceImpl implements AbhisheskService {


    @Autowired
    private AbhishekDao abhishekDao;    

    @Transactional
    public List<AbhishekDTO> findByMatchingCriteria(AbhishekDetailsSearchDTO searchDto) {
        return getAbs();
    }   


    public List<AbhishekDTO> getAbs(){
        Abhishekdetails absDt = this.abhishekDao.get(4L);
        return null;
    }

}

AbhishekDao是一个标准的DAO层接口,扩展了GenericDAO超级接口。

public interface AbhishekDao extends GenericDAO<Abhishekdetails, Long>{

    public List<Abhishekdetails> findByMatchingCriteria(AbhishekDetailsSearchDTO searchDto);

}

我的问题是:

findByMatchingCriteria 方法标记为 @Transactional.

此方法调用另一个未标记为 @Transactional 的方法 getAbs,它在 findByMatchingCriteria(自调用)中调用。

根据我的理解,因为 :

1)findByMatchingCriteria 在自身内部调用 getAbs(自调用),getAbs() 方法 不应该 运行 内部交易。因为它绕过了这里动态创建的代理

2)moreever getAbs 上没有 @Transactional 注释。

3) 但是当 getAbs 调用 this.abhishekDao.get(4L) 时一切正常,并检索到带有 ID 4L 的记录。 DAO bean 在其内部调用 sessionFactory.getCurrentSession() 以从 Db 获取对象。但为什么这有效? 因为那里 不应该 任何活跃的事务。

4)为什么上面的代码有效? Spring 事务管理上的很多帖子都指出自调用将不起作用。 (甚至 spring 文档)。

那为什么上面的设置有效?

我遗漏了什么吗?

或者我对spring交易的理解有误?

请回复,因为我在这里感到困惑

它的工作方式是: - AbhishekServiceImpl bean 包装在代理中。

  • findByMatchingCriteria@Transactional,因此在调用方法之前 Spring 从连接池获取新的数据库连接并将自动提交设置为 false。
  • 事务绑定到一个线程,因此该线程上的其他方法将使用该连接。
  • 方法findByMatchingCriteriagetAbs被执行
  • findByMatchingCriteria Spring 调用连接上的提交(或回滚,如果发生 RuntimeException)。

所以您的代码在 findByMatchingCriteria

左右的交易中

如果你在 getAbs 上有 @Transactional,但在 findByMatchingCriteria 上没有(反向调用)并且你在外部调用 findByMatchingCriteria服务。但是,如果您仅在服务之外调用 getAbs,它将处于事务中。

更清楚的例子:

@Service
public class MyServiceImpl implements MyService{   
    @Autowired
    private MyDao myDao;    
    @Transactional
    public List<T> transactionalMethod() {
        return this.myDao.get(4L);
    }   
    public List<T> notTransactionalMethod(){
        return transactionalMethod();
    }
}

其他一些class:

     @Component
        public class SomeClass {
            @Autowired
            private MyService myService;
            public void someMethod(){
                  myService.transactionalMethod();//will be in transaction. Here actualy you go to the proxy first and then it calls the real method. 
                  myService.notTransactionalMethod();//will not be in transaction and hibernate will throw an error. 
                                                     //You go to the proxy, but doesent do anything special because the method is not transactional and it calls the real method, 
                                                     //but here you dont't got trough the proxy so the @Transactional is ignored.
            }
        }