编程式事务:就是通过编码的方法实现的事务。(比如我们在使用hibernate的时候,需要手动调用beginTransaction()等方法。)
声明式事务:就是通过配置文件实现的事务。(比如如果我们使用spring,那么我们只需要在类名上面配置一个注解,就可以实现事务)
下面是我对spring的编程式事务和声明式事务查询的资料的总结:
1、spring的编程式事务分为:基于底层API的编程式事务管理;基于TransactionTemplate的编程式事务管理。他们的使用都需要和配置文件相结合。
2、spring的声明式事务:它的实现原理实际是建立在AOP的基础之上,是对方法的执行前后的拦截,在方法执行前和后加入事务。
3、声明式事务可以分为:
基于 TransactionInterceptor 的声明式事务;基于 TransactionProxyFactoryBean 的声明式事务;基于 <tx> 和 <aop> 命名空间的声明式事务;基于 @Transactional 的方式将声明式事务
查了很多资料,我们可以大概了解到这两个spring事务其实是相互补充的:
编程式事务的粒度比较细,它不但可以对方法加事务,还可以精确到对某一个代码块加事务。但是它的缺点是会让事务的代码遍布在我们写的代码当中,破坏了原有代码的逻辑性和可读性。
而声明式事务正是弥补了编程式事务的这个缺点,它可以保证我们写的业务逻辑代码不被因为插入大量事务处理代码而缺少可读性。但是声明式事务的缺点就是粒度比较粗,只能最小作用到方法级别,不能针对某个代码块。
在ITOO中最常用的是声明式事务中的基于@Transactional的方式声明事务的方法。
视频中讲到了spring和hibernate的集成,这样的话,spring事务就可以用hibernate的session对象了,hibernate中的sessionFactory中用来管理session的两个重要的方法就是openSession和getCurrentSession。下面咱们就从例子中了解一下这两个方法有什么不同:
* 使用getCurrentSession:
public void addUser(User user) {
Session session = null;
try {
session = HibernateUtils.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(user);
Log log = new Log();
log.setType("操作日志");
log.setTime(new Date());
log.setDetail("XXX");
LogManager logManager = new LogManagerImpl();
logManager.addLog(log);
Integer.parseInt("adfsadfdsf");
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
和
public void addLog(Log log) {
HibernateUtils.getSessionFactory().getCurrentSession().save(log);
}
这两个方法中用的是一个session,直接保存就行。
getCurrentSession方法不需要开启或关闭,它和当前的线程是绑定的,在事务结束以后会自动关闭。
使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
* 如果使用的是本地事务(jdbc事务)<property name="hibernate.current_session_context_class">thread</property>* 如果使用的是全局事务(jta事务)<property name="hibernate.current_session_context_class">jta</property>
* 使用opensession:
上面
addUser方法中的try...{}catch中的代码就会变成下面图片的代码:
那么就保证不了addlog方法和adduser方法用的是相同的session,所以咱们就知道了openSession是没有绑定线程的,使用完以后必须手动关闭。并且不能保证两个方法用的是同一个session。