为什么Spring Bean自我调用适用于事务

时间:2016-03-16 15:19:49

标签: java spring hibernate spring-mvc transactions

环境:

Tomcat 6

春季4

Hibernate 4

Spring MVC

代码:

我有以下服务层类:

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.

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

根据我的理解,自:

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

2)此外,getAbs没有@Transactional注释。

3)但是当getAbs调用this.abhishekDao.get(4L)时,一切正常,并且检索到ID 4L的记录。 DAO bean在其中调用sessionFactory.getCurrentSession()以从Db获取对象。但为什么这样呢? 因为不应该任何活动的交易。

4)为什么上面的代码有效?很多关于Spring Transaction管理的帖子都说自我调用不起作用。 (即使是春季文档)。

那为什么以上设置工作?

我在这里发生什么事吗?

或者我对春季交易的理解不正确?

因为我在这里感到困惑所以请你补偿

1 个答案:

答案 0 :(得分:3)

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

  • findByMatchingCriteria@Transactional,因此在调用该方法之前,Spring会从连接池获取新的数据库连接,并将auto commit设置为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();
    }
}

在其他一些课程中:

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