-
介绍
-
事务:一组业务操作ABCD,要么全部成功,要么全部不成功。
-
特性:ACID
- 原子性:整体
- 一致性:完整
- 隔离性:并发
- 持久性:结果
-
隔离问题:
- 脏读:一个事务读到另一个事务没有提交的数据
- 不可重复读:一个事务读到另一个事务已提交的数据(update)
- 虚读(幻读):一个事务读到另一个事务已提交的数据(insert)
-
隔离级别
-
read uncommitted:读未提交
-
read committed:读已提交
-
repeatable read:可重复读
-
serializable:串行化
-

-
mysql事务操作-基础
Connection conn = null; try{ //获得连接 conn = ...; //开启事务 conn.setAutoCommit(false); A B C D //提交事务 conn.commit(); }catch(){ //回滚事务 conn.rollback(); } -
mysql事务操作-Savepoint
- 需求:AB(必须),CD(可选)一个事务
Connection conn = null; Savepoint savepoint = null;//保存点,记录操作的当前位置,之后可以回滚到指定的位置。(可以回滚一部分) try{ //获得连接 conn = ...; //开启事务 conn.setAutoCommit(false); A B savepoint = conn.setSavepoint(); C D //提交事务 conn.commit(); }catch(){ //CD异常 if(savepoint != null){ //回滚到CD之前 conn.rollback(savepoint); conn.commit(); }else{ conn.rollback(); } } -
PlatformTransactionManager 平台事务管理器,spring要管理事务,必须使用事务管理器
- 进行事务配置时,必须配置事务管理器
-
TransactionDefinition:事务定义(事务详情,事务属性),spring用于确定事务具体详情,
- 例如:隔离级别,是否只读,超时时间
- 进行事务配置时,必须配置详情。spring将配置项封装到该对象
-
TransactionStatus:事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成
- spring底层根据状态进行相应操作
-
PlatformTransactionManager
-
DataSourceTransactionManager //jdbc HibernateTransactionManager //hibernate
//事务管理器通过“事务详情”,获取“事务状态”,从而管理事务 TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; //根据状态提交 void commit(TransactionStatus var1) throws TransactionException; //根据状态回滚 void rollback(TransactionStatus var1) throws TransactionException; -
-
TransactionStatus
public interface TransactionStatus extends SavepointManager, Flushable { boolean isNewTransaction(); //是否时新的事务 boolean hasSavepoint(); //是否有保存点 void setRollbackOnly(); //设置回滚 boolean isRollbackOnly(); //是否回滚 void flush(); //刷新 boolean isCompleted(); //是否完成 } -
TransactionDefinition
int ISOLATION_DEFAULT = -1;//隔离级别默认 int ISOLATION_READ_UNCOMMITTED = 1; int ISOLATION_READ_COMMITTED = 2; int ISOLATION_REPEATABLE_READ = 4; int ISOLATION_SERIALIZABLE = 8; int TIMEOUT_DEFAULT = -1;//默认超时时间。默认值-1.使用数据库底层的超时时间 int getPropagationBehavior();//传播行为 int getIsolationLevel();//隔离级别 int getTimeout();//获得超时时间 boolean isReadOnly();//是否只读(增删改:读写,查询:只读) @Nullable String getName();//配置事务详情名称。一般方法名称。例如:save、add*等-
转播行为
-
在业务之间如何来共享事务
int PROPAGATION_REQUIRED = 0;//支持当前事务,A如果有事务,B将使用该事务。如果A没有事务,B将创建一个新的事务 int PROPAGATION_SUPPORTS = 1;//支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将以事务执行 int PROPAGATION_MANDATORY = 2;//支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将抛异常 int PROPAGATION_REQUIRES_NEW = 3;//如果A有事务,将A的事务挂起,B创建一个新的事务,如果A没有事务,B创建一个新的事务 int PROPAGATION_NOT_SUPPORTED = 4;//如果A有事务,将A的事务挂起,B将以非事务执行,如果A没有事务,B将以非事务执行 int PROPAGATION_NEVER = 5;//如果A有事务,B将抛异常,如果A没有事务,B将以非事务执行 int PROPAGATION_NESTED = 6;//A和B底层采用保存点机制,形成嵌套事务 -
掌握
- PROPAGATION_REQUIRED【默认值】
- PROPAGATION_REQUIRES_NEW【创建新的事务】
- ROPAGATION_NESTED【嵌套】
-
-
-
案例:转账
-
搭建环境
- 创建表
use spring_day02; create table account( id int primary key auto_increment, username varchar(50), money int ); insert into account(username,money) values('jeck',100); insert into account(username,money) values('吕敬瑛','10000'); -
导入jar包
- 核心:4+1
- aop:4(aop联盟,spring aop、aspectj规范、spring aspect)
- 数据库:2 (jdbc/tx)
- 连接池:c3p0
-
dao
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { @Override public void out(String outer, Integer money) { this.getJdbcTemplate().update("update account set money = money - ? where username = ?", money, outer); } @Override public void in(String inner, Integer money) { this.getJdbcTemplate().update("update account set money = money + ? where username = ?", money, inner); } } -
service
public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer(String outer, String inner, Integer money) { accountDao.in(inner,money); accountDao.out(outer,money); } } -
xml
<!--数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day02"></property> <property name="user" value="root"></property> <property name="password" value="lv1117"></property> </bean> <!--dao--> <bean id="accountDao" class="com.adolph.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!--service--> <bean id="accountService" class="com.adolph.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> -
测试
@Test public void dome(){ String xmlPath = "com/adolph/applicationContext.xml"; ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); AccountServiceImpl accountService = applicationContext.getBean("accountService", AccountServiceImpl.class); accountService.transfer("lin","jeck",100); } -
手动管理事务(了解)
-
spring底层使用 TransactionTemplate事务模板进行操作
-
操作
- service需要获得TeansactionTemplate
- spring在配置模板,并注入给service
- 模板需要注入事务管理器
- 配置事务管理器:DataSourceTransactionManager
-
修改service
//需要spring注入模板 private TransactionTemplate transactionTemplate; public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } @Override public void transfer(final String outer, final String inner, final Integer money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { accountDao.in(inner,money); accountDao.out(outer,money); } }); } -
修改xml
<!--service--> <bean id="accountService" class="com.adolph.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> <property name="transactionTemplate" ref="transactionTemplate"></property> </bean> <!--创建模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="txManger"></property> </bean> <!--事务管理器,管理器需要事务,事务从Connection获得,连接从连接池DataSource获得--> <bean id="txManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
-
-