spring事务
- spring事务提供了事务管理器DataSourceTransactionManager,可以为我们对事务进行管理,处理事务的提交、回滚.
- spring还提供了事务的传播行为
一、事务的使用
1.spring事务使用方式有俩种,一种基于注解使用,一种基于配置文件的使用,不过不论哪种使用,都需要配置事务管理器
事务管理器配置,dataSource是数据源的配置,先配置数据源。
<!--配置数据源-->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"/>
<property name="jdbcUrl" value="${url}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<!--最小连接数量-->
<property name="minPoolSize" value="5"/>
<!--最大连接数量-->
<property name="maxPoolSize" value="10"/>
<!--初始连接数量-->
<property name="initialPoolSize" value="7"/>
<!--连接的最大存活时间,为0则不清除-->
<property name="maxIdleTime" value="60"/>
</bean>
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
xml配置事务
<!--配置通知,tx:method是指定为哪些方法织入事务-->
<!--propagation 是事务的传播行为-->
<!--isolation 事务的隔离级别,使用default则根据数据库引擎的隔离级别-->
<!--rollback-for 指定事务回滚遇到的异常,默认就是RuntimeException-->
<!--no-rollback-for 指定事务遇到某个异常不会滚->
<!--timeout 设置事务超时时间,单位为秒,-1则永不超时-->
<!--read-only 设置事务为可读,好像说会有优化...,true为可读-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" rollback-for="RuntimeException" no-rollback-for="IOException" timeout="-1" read-only="false"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--配置advisor,依赖通知和切点,这样事务管理器就可以进行事务管理了-->
<!--事务使用advisor这个,其他情况使用aop则用aspect,事务好像也可以用这个,不过没用尝试过,具体不清楚-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.xxf.demo.service.impl.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
@Transactional
注解使用事务,首先开启事务注解扫描
<!--transactionManager为事务管理器-->
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional可以用于方法上以及类上、接口上
spring建议使用在方法或者类上,不要使用到接口上,使用到接口上可能在代理时会出现问题,具体问题每探究过
代理分为jdk的接口代理,与cglib的继承类代理,默认使用接口代理,如果使用cglib代理可能就会出现问题
@Transactional注解参数的使用与xml配置是一样的
二、spring事务的传播行为
-
REQUIRED 必须使用事务,当前若不存在事务,则创建一个事务。
-
SUPPORTS 支持事务,当前若不存在事务,则以非事务执行,此时,事务管理器,不会帮我们进行回滚,提交,会使用数据库默认状态,一般mysql数据库默认都时提交的
-
MANDATORY 必须已事务执行,如果当前不存在事务,那么会抛出异常
-
REQUIRES_NEW 永远都新建事务,如果当前存在事务,那么挂起当前事务,新建一个
-
NOT_SUPPORTED 不支持事务,如果当前存在事务,那么将事务挂起,此时,跟SUPPORTS一样.
-
NEVER 不支持事务,如果当前存在事务,那么会抛出异常
-
NESTED 嵌套事务,如果当前存在事务,那么为该事务生成子事务,子事务本质上还是跟外部事务是同一个,子事务的实现逻辑是为子事务设置了一个SavePoint(保存节点,这里没去深究过,大致意思就是可以用于回溯,回到之前的状态),当出现异常时,就会回到之前保存的节点
spring事务传播行为总结
1.当操作为非事务时,事务管理器不会帮我们管理,这时会采用数据库默认的操作,此时你会发现,connection永远都会进行提交
2.事务回滚,当事务内部出现异常时就会回滚,如果同属一个事务,并且出现了异常,异常还返回给aop为我们代理的service,
那么这个事务就会进行回滚。所以还看一个事务是否回滚,要关注它的异常是否返回给了aop为我们代理的service