Spring的事务管理
事务概念
一:.什么是事务
一组操作呀,要么都成功,有一个失败所有都失败。
事务是一系列的动作,一旦其中有一个动作出现错误,必须全部回滚,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态,
避免出现由于数据不一致而导致的接下来一系列的错误。事务的出现是为了确保数据的完整性和一致性,在目前企业级应用开发中,事务管理是必不可少的。
二:.事务的特性
1.原子性(Atomicity)事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
2.一致性(Consistency)事务在完成时,必须是所有的数据都保持一致状态。
3.隔离性(Isolation)并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性。
4.持久性(Durability)一旦事务完成,数据库的改变必须是持久化的。
三:不考虑隔离性产生读问题
在企业级应用中,多用户访问数据库是常见的场景,这就是所谓的事务的并发。事务并发所可能存在的问题:
1.脏读:一个事务读到另一个事务未提交的更新数据。
2.不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。
3.幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
4.丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。
四:解决读问题
(1)设置隔离级别
Spring事务管理api
1spring事务管理俩种方式
第一种:编程式(事务管理)
第二种:声明式事务管理
(1)基于xml配置文件实现
(2)基于注解实现
2.spring事务管理的api介绍
接口
PlatformTransactionManager
事务管理器
(1)spring针对不同的dao层框架,提供接口不同的实现类
事务 说明
org.springframeworkjdbc.datasource.DataSource 使用springJDBC或IBatista进行持久化数据时使用
TransactionManager
org.springframework.orm.hibernate5.Hibernate 使用hibernate5进行持久化数据时使用
TransactionManager
搭建转账环境
1.创建数据库表,添加数据
id username salary
1 小李 2000
2 小马 1500
2.创建service和dao类,实现注入关系
配置文件
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
>
<!--配置c3po-->
<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/student_teacher"></property>
<property name="user" value="root"></property>
<property name="password" value="123"></property>
</bean>
<bean id="orderService" class="ZZQ_Service.OrderService">
<property name="orderDao" ref="orderDao"></property>
</bean>
<bean id="orderDao" class="ZZQ_Service.OrderDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
(1)servicve层又叫业务逻辑层
public class OrderService {
private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
/**
* 调用dao的方法
* 业务逻辑层没写业务
*/
public void accountMoney() {
orderDao.lsessMaoey();
orderDao.moreMoney();
}
}
(2)dao层,单纯对数据库操作层,在dao层不添加业务
public class OrderDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 做对数据库操作的方法,不写业务逻辑
*/
//小王少的方法
public void lsessMaoey() {
String sql="update account set salary=salary-? where username=?";
jdbcTemplate.update(sql, 1000,"小李");
}
//小马多钱的方法
public void moreMoney() {
String sql="update account set salary=salary+? where username=?";
jdbcTemplate.update(sql, 1000,"小马");
}
}
(3)测试代码
public class TestMethod {
@Test
public void testOrder() {
ApplicationContext applicationContext=
new ClassPathXmlApplicationContext("bean.xml");
OrderService orderService = (OrderService) applicationContext.getBean("orderService");
orderService.accountMoney();
}
}
3产生问题
(1)如果小王少了1000之后,出现异常,小马保护会多1000钱丢失了
4.解决
Spring事务的隔离级别
名称 值 解释
ISOLATION_DEFAULT -1 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应
ISOLATION_READ_UNCOMMITTED 1 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。
ISOLATION_READ_COMMITTED 2 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ 4 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。
ISOLATION_SERIALIZABLE 8 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。
(1)添加事务解决,出现异常进行回滚操作
声明式事务管理(xml) 1.配置文件方式用aop原理配置
<!--第一步:配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入DataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--第二步:配置事务增强-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!--做事务操作-->
<tx:attributes>
<!--设置事务操作方法的匹配原则-->
<tx:method name="account*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--第二三步:配置切面-->
<aop:config>
<aop:pointcut expression="execution(* ZZQ_Service.OrderService.*(..))" id="pointcut1"/>
<!--切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
</aop:config>
声明式事务管理(注解)
第一步.配置事务管理器
<!--第一步:配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入DataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
第二步 配置事务注解
<!--第二步开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
第三步在要使用事务的方法所在类上面添加注解
@Transactional
public class OrderService {