标签:std 事务管理器 右键 级别 rman sql -- getbean bsp
-------------------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;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
public void lessMoney(String from, int money) { String sql="update account set money=money-? where name=?"; jdbcTemplate.update(sql, money, from); }
public void 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;
public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; }
public void transfer(String from,String to,int money) { accountDao.lessMoney(from, money); accountDao.moreMoney(to, money); }
} |
(3)在配置文件中进行配置
applicationContext.xml:
<?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: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">
<!-- 配置内置连接池 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <!-- jdbc:mysql:///tx_db 是 jdbc:mysql://localhost:3306/tx_db 的简写 --> <property name="url" value="jdbc:mysql:///tx_db"/> <property name="username" value="root"/> <property name="password" value="8888"/> </bean>
<!-- 配置对象并注入属性 --> <bean id="accountService" class="com.siwuxie095.service.AccountService"> <property name="accountDao" ref="accountDao"></property> </bean>
<bean id="accountDao" class="com.siwuxie095.dao.AccountDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 在 JdbcTemplate 源代码中有属性 dataSource 和其 set 方法,所以可以注入 --> <property name="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 public void testService() {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService=(AccountService) context.getBean("accountService");
accountService.transfer("小白", "小黑", 1000); }
} |
3、问题所在
上面的程序虽然可以正常运行,并实现转账功能,但如果在一个人
转出钱时出现异常,另一个人就不会收到钱
即 一个人少钱,另一个人却没有多钱,导致钱丢失了
4、解决方法
添加事务管理,当出现异常时进行回滚
【made by siwuxie095】
标签:std 事务管理器 右键 级别 rman sql -- getbean bsp
原文地址:http://www.cnblogs.com/siwuxie095/p/7417314.html