环境:
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管理的帖子都说自我调用不起作用。 (即使是春季文档)。
那为什么以上设置工作?
我在这里发生什么事吗?
或者我对春季交易的理解不正确?
因为我在这里感到困惑所以请你补偿
答案 0 :(得分:3)
它的工作方式是: - AbhishekServiceImpl bean包含在代理中。
findByMatchingCriteria
是@Transactional
,因此在调用该方法之前,Spring会从连接池获取新的数据库连接,并将auto commit设置为false。findByMatchingCriteria
和getAbs
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.
}
}