Spring事务管理
来源:互联网 发布:阿里云服务器发票类别 编辑:程序博客网 时间:2024/05/21 23:06
-------------------siwuxie095
Spring 事务管理
(一)事务的相关概念
1、什么是事务
事务是逻辑上的一组操作,构成这组操作的各个逻辑单元,
要么一起成功,要么一起失败
2、事务特性(简称ACID)
(1)原子性:强调事务的不可分割
(2)一致性:事务执行前后,数据的完整性保持一致
(3)隔离性:一个事务在执行的过程中,不应该受到其他事务的干扰
(4)持久性:事务一旦结束,数据就持久到数据库
3、如果不考虑隔离性引发安全性问题
(1)脏读
一个事务读到了另一个事务未提交的数据
(2)不可重复读
一个事务读到了另一个事务已经提交的 update 的数据,导致多次查询结果不一致
(3)幻读(也称虚读)
一个事务读到了另一个事务已经提交的 insert 的数据,导致多次查询结果不一致
4、解决读问题:设置事务隔离级别
(1)未提交读:脏读、不可重复读、幻读都有可能发生
(2)已提交读:避免脏读,但不可重复读和幻读有可能发生
(3)可重复读:避免脏读和不可重复读,但幻读有可能发生
(4)可串行化:避免以上所有读问题
(二)Spring 事务管理 API
1、Spring 事务管理有两种方式
(1)编程式事务管理:手动编写代码实现事务管理
(2)声明式事务管理:通过一段配置实现事务管理(建议)
1)基于XML 的方式
2)基于注解的方式
2、Spring 事务管理 API 介绍
(1)接口:PlatformTransactionManager(事务管理器)
Spring 为不同的持久层框架提供了 PlatformTransactionManager 接口的不同实现类
ORM 持久层框架
实现类
Spring JDBC
DataSourceTransactionManager
iBatis
DataSourceTransactionManager
MyBatis
DataSourceTransactionManager
Hibernate
HibernateTransactionManager
JPA
JpaTransactionManager
JDO
JdoTransactionManager
JTA
JtaTransactionManager
(2)接口:TransactionDefinition(事务定义)
用来定义事务相关属性,给事务管理器使用
1)隔离级别
2)传播行为
3)超时信息
4)是否只读
(3)接口:TransactionStatus(事务状态)
事务运行过程中,记录每个时间点的事务状态信息
即事务管理器根据事务定义的信息进行事务的管理,在此过程中
会产生一些状态,将事务状态记录下来
(三)测试:以转账为例
1、在MySQL 中手动创建数据库和表
数据库名:tx_db,表名:account,字段:id、name、money
手动添加数据,用作测试
2、具体实现
(1)编写一个Dao 类
AccountDao.java:
package com.siwuxie095.dao;
import org.springframework.jdbc.core.JdbcTemplate;
public class AccountDao {
private JdbcTemplate jdbcTemplate;
publicvoid setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
publicvoid lessMoney(String from,int money) {
String sql="update account set money=money-? where name=?";
jdbcTemplate.update(sql, money, from);
}
publicvoid moreMoney(String to,int money) {
String sql="update account set money=money+? where name=?";
jdbcTemplate.update(sql, money, to);
}
}
(2)编写一个Service 类
AccountService.java:
package com.siwuxie095.service;
import com.siwuxie095.dao.AccountDao;
public class AccountService {
private AccountDao accountDao;
publicvoid setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
publicvoid transfer(String from,String to,int money) {
accountDao.lessMoney(from, money);
accountDao.moreMoney(to, money);
}
}
(3)在配置文件中进行配置
applicationContext.xml:
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--配置内置连接池 -->
<beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>
<!--
jdbc:mysql:///tx_db是 jdbc:mysql://localhost:3306/tx_db的简写
-->
<propertyname="url"value="jdbc:mysql:///tx_db"/>
<propertyname="username"value="root"/>
<propertyname="password"value="8888"/>
</bean>
<!--配置对象并注入属性 -->
<beanid="accountService"class="com.siwuxie095.service.AccountService">
<propertyname="accountDao"ref="accountDao"></property>
</bean>
<beanid="accountDao"class="com.siwuxie095.dao.AccountDao">
<propertyname="jdbcTemplate"ref="jdbcTemplate"></property>
</bean>
<beanid="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate">
<!--在 JdbcTemplate源代码中有属性 dataSource和其 set方法,所以可以注入 -->
<propertyname="dataSource"ref="dataSource"></property>
</bean>
</beans>
(4)编写一个测试类
TestDemo.java:
package com.siwuxie095.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.siwuxie095.service.AccountService;
public class TestDmo {
/**
*手动加上 @Test以进行单元测试(将自动导入 JUnit 4的 jar包)
*
*选中方法名,右键->Run As->JUint Test
*/
@Test
publicvoid testService() {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService=(AccountService) context.getBean("accountService");
accountService.transfer("小白","小黑",1000);
}
}
3、问题所在
上面的程序虽然可以正常运行,并实现转账功能,但如果在一个人
转出钱时出现异常,另一个人就不会收到钱
即一个人少钱,另一个人却没有多钱,导致钱丢失了
4、解决方法
添加事务管理,当出现异常时进行回滚
【made by siwuxie095】
- 事务管理之Spring事务管理
- Spring事务管理
- spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring 事务管理
- Spring事务管理
- spring 事务管理
- spring 事务管理
- spring 事务管理
- spring事务管理
- Spring 事务管理
- Spring事务管理
- spring事务管理
- spring 事务管理
- MarkdownPad编写符号
- 欢迎使用CSDN-markdown编辑器
- proto生成shell
- 欢迎使用CSDN-markdown编辑器
- HDU
- Spring事务管理
- 朋友
- Android 常用ADB命令
- SQL Server查询优化方法
- IntelliJ IDEA下的使用git
- Python 和perl 中的字节和字符
- java 生成excel表传给前端下载
- html5框架
- 初试OpenCV(Ubuntu)