1.事务代码配置
1.1 代码配置
public class ApplyUserDAOImpl implements ApplyUserDAO{ @Autowired private JdbcTemplate jdbcTemplate; @Autowired private TransactionTemplate transactionTemplate; //基于transactionManager的精确事务控制************** public Boolean batchUpdate1(){ //不需要事务的先前处理逻辑 return transactionTemplate.execute(new TransactionCallback<Boolean>(){ @Override public Boolean doInTransaction(TransactionStatus status) { try{ //做一些事物处理的事情 }catch(Exception e){ <span style="white-space:pre"> </span>status.setRollbackOnly(); return Boolean.FALSE; } return Boolean.TRUE; } }); //不需要事务的后续处理逻辑 } //基于注解的事务************************************* @Transactional( value="transactionManager", //事务管理器名称,在多个数据源下可能有多个事务管理器使用 timeout=200, //自动回滚的超时时间 noRollbackFor=RuntimeException.class, //遇到什么样的异常不回滚事务 noRollbackForClassName="java.lang.RuntimeException", rollbackFor=NullPointerException.class, //什么样的异常回滚事务 rollbackForClassName="java.lang.NullPointerException", isolation=Isolation.READ_COMMITTED, //事务的隔离级别(读未提交,读提交,可重复读,串行化) propagation=Propagation.REQUIRED, //事务的传播方式 readOnly=false) public Boolean batchUpdate2(){ return null; } //基于xml配置的事务*********************************** public Boolean batchUpdate3(){ return null; } }
1.2 事务的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <context:annotation-config/> <bean id="applyUserDAO" class="liyin.jdbc.mysqlDAO.impl.ApplyUserDAOImpl"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="zhexuehan"></property> <property name="password" value="123456"></property> <property name="jdbcUrl" value="jdbc:mysql://192.168.1.150:3306/development"></property> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="initialPoolSize" value="2"></property> <property name="maxPoolSize" value="100"></property> <property name="minPoolSize" value="2"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 精确事务控制 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean> <!-- 注解事务控制 @Transctional--> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- 基于xml配置的事务 --> <tx:advice id="txAdivice" transaction-manager="transactionManager"> <!-- 事务属性配置 --> <tx:attributes> <tx:method name="*" isolation="REPEATABLE_READ"/> <!-- 所有方法都使用可重复读事务隔离界别 --> <tx:method name="*" rollback-for="java.lang.NullPointerException"/><!-- 所有方法回滚方式 --> <tx:method name="add*" propagation="REQUIRED"/> <!-- 以add开始的方法使用REQUIRED事务传播行为 --> <tx:method name="get*" read-only="true"/> <!-- 以get开始的方法为只读事务 --> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="txPointCut" expression="excution(*liyin.jdbc.mysqlDAO.impl.ApplyUserDAOImpl.*(..))"/><!-- 应用于ApplyUserDAOImpl所有方法 --> <aop:advisor advice-ref="txAdivice" pointcut-ref="txPointCut"/><!-- 编织事务 --> </aop:config> </beans>
2. 事务解释
2.1数据库并发问题
A.丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖(A和B事务并发执行,A事务执行更新后,提交;B事务在A事务更新后,B事务结束前也做了对该行数据的更新操作,然后回滚,则两次更新操作都丢失了)。
B.脏读:一个事务读到另一个事务未提交的更新数据(A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据)。
C.不可重复读:一个事务读到另一个事务已提交的更新数据(A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了)。
D. 覆盖更新:这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据(即A事务更新数据,然后B事务更新该数据,A事务查询发现自己更新的数据变了)。
E.虚读(幻读):一个事务读到另一个事务已提交的新插入的数据(A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了)。
2.1事务隔离界别
A.Read Uncommited 读未提交:一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。
B.Read Committed 读提交:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
C.Repeatable Read 可重复读:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但对于此事务中读取的记录,其他事务只能读不能修改。
D.Serializable 串行化:一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。) MYSQL的默认隔离级别。