Spring事务和数据库事务到底是什么关系?
Spring事务是如何传递到数据库的?
首先,我们来回忆一下jdbc这个api,这是java操作数据库的入口,是java操作数据库的通道,是我们与数据库打交道的必经之路。那么,是不是说,Spring的事务控制就是通过jdbc传递到数据库,然后执行的呢?我个人觉得,就是这样,并且也只有这样。
继续回忆,jdbc怎么操作数据库呢?首先建立连接,然后执行增删改查,然后关闭数据库连接。如果你需要事务控制,那么就把Connection的自动提交关闭:
con.setAutoCommit(false);
然后在需要提交事务时显示提交就可以了。
con.commit();
这就是jdbc操作数据库的方式。
接下来,我们继续深入研究一下,应用程序通过jdbc把数据库操作sql发送到DBMS以后,DBMS如何进行事务控制呢?
这个就是数据库的工作原理了,如果数据库支持事务,那么数据库首先会开启事务,然后等到所有的sql都执行完以后,再提交事务。就像我们在存储过程中显式的提交事务一样。但是数据库如何知道在哪个sql前开启事务,执行到哪里再关闭事务的呢?这个就是jdbc的实现细节了,感兴趣的可以研究一下jdbc的源代码。
到这里,我们基本上可以回答开篇提出的疑问了。Spring整合Mybatis的架构中,Mybatis是应用程序与数据库通道,是两者交互的唯一通道。而Mybatis框架封装的就是jdbc。
接下来,我们还要探讨一下,Spring的事务传播机制与数据库的隔离级别的关系。
答:二者之间没有关系。
Spring的事务传播机制中的当前事务,指的是当前Spring的事务,还是当前数据库的事务?
spring事务传播机制如下:
REQUIRED
SUPPORTS
MANDATORY
REQURIED_NEW
NOT_SUPPORTED
NEVER
NESTED
数据库的隔离级别如下:
READ_UNCIMMITED
READ_COMMITED
REPEATABLE_READ
SERIALIZABLE
默认设置是第一种:REQURIED,什么意思呢?就是说,支持当前事务,如果当前没有事务,就新建一个事务,这是网上的说法,说实话,这个说的有点晦涩难懂,如果不看Spring注解相关源码,根本理解不了。
于是乎,我就去看事务的源码了,看看Spring这个事务传播机制到底是个什么意思。
源码没看懂,先看一下@Transational注解的定义,内容还是挺丰富的。主要包含以下属性:
Spring事务与数据库事务的交互原理关于@Transational注解,需要注意以下几个问题:
注意点: Spring默认情况下会对(RuntimeException)及其子类来进行回滚,在遇见Exception及其子类的时候则不会进行回滚操作。
注意点: @Transactional既可以作用于接口,接口方法上以及类已经类的方法上。但是Spring官方不建议接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。 Spring默认使用的是jdk自带的基于接口的代理,而没有使用基于类的代理CGLIB。
网友评论