Spring的事务管理
理解事务之前:说一个列子,取钱,比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱;然后ATM出1000元钱。这两个步骤必须是要么都执行要么都不执行。如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话,这对双方都是极好的。
事务就是用来解决类似问题的。事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性。
事务的特性:
- 原子性:要么全做,要么全不做。
- 一致性:一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
- 隔离性:可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
- 持久性: 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
1.事务管理的核心接口
spring的jar包中,包含一个名为spring-tx-4.3.6RELEASE的jar包。该包就是spring提供的用于事务管理的依赖包。在该包的org.springframework.transaction包中,包含事务管理的三个核心接口。
- PlatformTransactionManager接口:
提供的平台事务管理器,用于管理事务。
TransactionStatus getTransaction(TransactionDeFinition deFinition):用于获取事务状态信息。Spring 将 xml 中配置的事务详细信息封装到对象 TransactionDeFinition 中,然后通过事务管理器的 getTransaction() 方法获得事务的状态(TransactionStatus),并对事务进行下一步的操作。
void commit(TransactionStatus status):用于提交事务。
void rollback(TransactionStatus status):用于回滚事务。
- String getName():获取事务对象名称。
- int getIsolationLevel():获取事务的隔离级别。
- int getPropagationBehavior():获取事务的传播行为。
- int getTimeout():获取事务的超时时间。
- boolean isReadOnly():获取事务是否只读。
- TransactionStatus接口
TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。其中包含六个操作.
2.声明式事务管理:
2.1:基于XML的方式:
接口类
//outUser汇款人 inUser收款人
public void transfer(String outUser,String inUser,Double money);
}
实现类
public void transfer(String outUser, String inUser, Double money) {
this.jdbcTemplate.update("update account set balance = balance +?"+
"where username = ?",money,inUser);
this.jdbcTemplate.update("update account set balance = balance -?"+
"where username = ?",money,outUser);
}
控制类
@Controller
public class AccountController {
}
实体类
public class Account {
private Integer id;
private String username;
private Double balance;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String toString() {
return "Account [id=" + id + ", "
+ "username=" + username + ", "
+ "balance=" + balance + "]";
}
}
测试类
public class TransactionTest {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClasspathXmlApplicationContext("bean.xml");
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
accountDao.transfer("Tom", "man", 1000.0);
System.out.println("转账成功----------");
}
}
基于事务管理的配置代码----》重点(学习里面代码注释)
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xs
">
<!-- 1.配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动-->
<property name="driverClassName" value="com.MysqL.cj.jdbc.Driver"/>
<!--连接数据库的url-->
<property name="url" value="jdbc:MysqL://localhost:3306/spring"/>
<!--连接数据库的用户名-->
<property name="username" value="root"/>
<!--连接数据库的密码-->
<property name="password" value="123456"/>
</bean>
<!-- 2.配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--默认必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 3.定义id为accountDao的Bean-->
<bean id="accountDao" class="com.lz.jiaotong.dao.impl.AccountDaoImpl">
<!--将jdbcTempla注入到accountDao实例中-->
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- 4.事务管理器,依赖于数据源-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 5.编写通知,对事务增强,需要编写对切入点和具体执行事务细节-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="required" isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- 6.编写aop 让spring对目标自动生成代理需要使用AspectJ的表达式-->
<aop:config>
<aop:pointcut expression="execution(* com.lz.jiaotong.dao.impl.*.*(..))" id="txpointcut"/>
<!-- 切面 :将切入点与通知整合-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txpointcut"/>
</aop:config>
</beans>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。