spring事务管理
来源:互联网 发布:javascript跑马灯效果 编辑:程序博客网 时间:2024/05/22 05:00
理论篇:
什么是事务?
举个简单点的例子,张三和李四之间相互转账,假设张三通过支付宝转给李四400元,首先会修改张三的账户余额,把张三的总金额减去400,然后再找到李四的账户,为李四的账户增加400元;我们说这才是一件完整的事情,很简单的这件事情就是张三给李四转账,这个事情的任务就是李四要收到张三的400元,如果张三因为转账途中断网断电了,那就说明这个事务不完整;所以我们要控制这个事务要么一起成功,一起失败;
事务的四大特性:
原子性:所谓原子是指我这个单位已经是最小不可分割的了,一个事务应该是具有原子性的,他们应该是要么一起改变状态,要么都不会改变;
一致性:一致性是指事务在改变前后的数据完整性一定要保持一致,这里假设张三有2000元转给李四400元后还剩下1600,李四假设也有2000元,接收到了张三的400元后,变成了2400,他们的总数加起来还是4000;中间没有丢失任何金额和数据;
隔离性:隔离性指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间的数据要隔离起来;这里解释起来就比较复杂了,这里说张三正在向李四转账400元的途中,又有一个叫王五的也在给李四转账,那么我们说一个事务不能被另外一个事务所影响,他们之间必须要有一个先后顺序;我们的数据库都有自己定义的一套隔离级别,具体实现后面再说;
持久性:持久性是指一个事务一旦提交了,它对数据库的改变就是永久性的,即使数据库忽然断了,那么也要保证不会对其事务有任何影响;
Spring事务管理的的主要三个接口:
PlatformTransactionManager 事务管理器
TransactionDefinition 事务定义信息(隔离,传播,超时,只读)
TransactionStatus 事务具体运行状态
PlatformTransactionManager会根据不同的ORM框架来选择不同的实现类,下面列举几个主要实现
TransactionDefinition:
主要来控制我们事务的隔离级别,如果不控制隔离级别就会发生脏读,不可重复读和幻读的问题;
脏读:一个事务读取了另一个事务改写但未提交的数据,如果这些数据被回滚,则读到的数据是无效的;
不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同;
幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务 就会发现有些原来没有的记录;
实战篇:
第一种编程式事务管理,所谓编程式是指,我们会事先配置好事务的模板,但是当我们需要事务的时候会采用编程的时候去执行事务;
我们先创建一个数据库表结构,模拟上面的转账;
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `money` double DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;INSERT INTO `account` VALUES ('1', '张三', '1000');INSERT INTO `account` VALUES ('2', '李四', '1000');INSERT INTO `account` VALUES ('3', '王五', '1000');
接着再配置一下spring容器,再里面声明一下事务:
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd"><!-- 引入外部的属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}" /><property name="jdbcUrl" value="${jdbc.url}" /><property name="user" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!-- 配置业务层类 --><bean id="accountService" class="com.zs.spring.demo1.AccountServiceImpl"><property name="accountDao" ref="accountDao" /><!-- 注入事务管理的模板 --><property name="transactionTemplate" ref="transactionTemplate" /></bean><!-- 配置DAO类(简化,会自动配置JdbcTemplate) --><bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl"><property name="dataSource" ref="dataSource" /></bean><!-- 配置DAO类(未简化) --><!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean> --><!-- ==================================1.编程式的事务管理=============================================== --><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean></beans>声明DAO:
public interface AccountDao {/** * @param out:转出账号 * @param money:转账金额 */public void outMoney(String out,Double money);/** * * @param in:转入账号 * @param money:转账金额 */public void inMoney(String in,Double money);}
/** * @param out:转出账号 * @param money:转账金额 */@Overridepublic void outMoney(String out, Double money) {String sql = "update account set money = money-? where name = ?";this.getJdbcTemplate().update(sql, money, out);}/** * @param in:转入账号 * @param money:转账金额 */@Overridepublic void inMoney(String in, Double money) {String sql = "update account set money = money+? where name = ?";this.getJdbcTemplate().update(sql,money,in);}声明service
public interface AccountService {/** * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */public void transfer(String out,String in,Double money);}
public class AccountServiceImpl implements AccountService {//注入转账的DAOprivate AccountDao accountDao;//注入事务管理的模板private TransactionTemplate transactionTemplate;/** * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */@Overridepublic void transfer(final String out, final String in, final Double money) {/*accountDao.outMoney(out, money);//int i = 1/0;accountDao.inMoney(in, money);*/transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {accountDao.outMoney(out, money);//int i = 1/0;accountDao.inMoney(in, money);}});}public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}public void setTransactionTemplate(TransactionTemplate transactionTemplate) {this.transactionTemplate = transactionTemplate;}}测试:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:applicationContext1.xml")public class TransactionTest {@Resource(name="accountService")private AccountService accountService;@Testpublic void demo1(){accountService.transfer("张三", "李四", 200d);}}使用XML配置声明式的事务管理(原始方式):
<!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 配置业务层的代理 --><bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 配置目标对象 --><property name="target" ref="accountService" /><!-- 注入事务管理器 --><property name="transactionManager" ref="transactionManager"></property><!-- 注入事务的属性 --><property name="transactionAttributes"><props><!-- prop的格式:* PROPAGATION:事务的传播行为* ISOTATION:事务的隔离级别* readOnly:只读* -EXCEPTION:发生哪些异常回滚事务* +EXCEPTION :发生哪些异常不回滚事务 --><prop key="transfer">PROPAGATION_REQUIRED</prop><!-- <prop key="transfer">PROPAGATION_REQUIRED,readOnly</prop> --><!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> --></props></property></bean>使用XML配置声明式的事务管理,基于tx/aop:
<!-- ==================================3.使用XML配置声明式的事务管理,基于tx/aop=============================================== --><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 配置事务的通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- propagation:事务传播行为isolation:事务的隔离级别read-only:只读rollback-for:发生哪些异常回滚no-rollback-for:发生哪些异常不回滚timeout:过期信息 --><tx:method name="transfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!-- 配置切面 --><aop:config><!-- 配置切入点 --><aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/><!-- 配置切面 --><aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/></aop:config>使用注解配置声明式事务
<!-- ==================================4.使用注解配置声明式事务============================================ --><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 开启注解事务 --><tx:annotation-driven transaction-manager="transactionManager"/>
/** * * @author admin * * *@Transactional中的的属性 *propagation:事务的传播行为 *isolation:事务的隔离级别 *readOnly:只读 *rollbackFor:发生哪些异常回滚 *noRollbackFor:发生哪些异常不回滚 *rollbackForClassName 根据异常类名回滚 */@Transactionalpublic class AccountServiceImpl implements AccountService {//注入转账的DAOprivate AccountDao accountDao;/** * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */@Overridepublic void transfer( String out, String in, Double money) {accountDao.outMoney(out, money);//int i = 1/0;accountDao.inMoney(in, money);}public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}}
- 事务管理之Spring事务管理
- Spring事务管理
- spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring 事务管理
- Spring事务管理
- spring 事务管理
- spring 事务管理
- spring 事务管理
- spring事务管理
- Spring 事务管理
- Spring事务管理
- spring事务管理
- spring 事务管理
- 不久前被问到的一个问——GDB为什么能够修改一个进程中的数据
- Android使用本地缓存解析远程服务器JSON数据
- 基于泰勒展开式的高精三角函数实现,方法三
- Java基础复习(二)
- HNOI 2016 暴力之旅
- spring事务管理
- 用Apache httpclient模拟登陆学生个人信息系统
- Java编程思想--格式化说明符
- 专题二1005
- 正态分布的由来
- 专题二 1001
- 207 Course Schedule
- 根据类Student的定义,创建五个该类的对象,输出每个学生的信息, 计算并输出这五个学生Java语言成绩的平均值,以及计算并输出他们Java语言成绩的最大值和最小值。
- Windows安装MySQL5.7