【问题标题】:Why Spring Bean Self Invocation is working here for Transaction为什么 Spring Bean Self Invocation 在这里为 Transaction 工作
【发布时间】:2016-07-02 13:57:12
【问题描述】:

环境:

雄猫 6

春季 4

休眠 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 管理的帖子都表明自我调用不起作用。 (甚至是春季文档)。

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

我在这里有什么遗漏吗?

还是我对spring事务的理解有误?

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

【问题讨论】:

    标签: java spring hibernate spring-mvc transactions


    【解决方案1】:

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

    • findByMatchingCriteria@Transactional,所以在调用该方法之前,Spring 从连接池中获取新的数据库连接并将自动提交设置为 false。
    • 事务绑定到一个线程,因此该线程上的其他方法将使用此连接。
    • 方法findByMatchingCriteriagetAbs被执行
    • findByMatchingCriteria Spring 在连接上调用commit 之后(如果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.
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多