框架(三)Spring框架之Spring的事务管理

1.事务的基础知识

1.1事务的特性:
原子性:事务不可分割
一致性:事务执行前后数据完整性保持一致
隔离性:一个事务的执行不应该受到其他事务的干扰
持久性:一个事务结束后,数据就持久化到数据库
1.2不考虑隔离性引发的安全问题
++++读问题:
脏读------------一个事务读到另一个事务未提交的数据
不可重复读—一个事务读到另一个事务已经提交的update的数据,导致一个事务中多次查询结果不一致
幻读------------一个事务读到另一个事务已经提交的insert的数据,导致一个事务中多次查询结果不一致
+++++写问题:
丢失更新
1.3解决读的问题:
++++设置事务隔离级别
Read uncommitted(未提交读):任何读问题都解决不了;={}
Read committed(已提交读):解决脏读,无法解决不可重复读和幻读;
={orancle默认}
Repeatable read(重复度):解决脏读和不可重复读,无法解决幻读;
==={mysql默认}
Serializable:解决所有读问题;

2.Spring事务管理的API

2.1Spring 的事务传播行为==========>>>>解决特别复杂的业务方法之间的调用
===2.1.1.保证多个操作在同一个事务中【一般使用默认的】
====PROPAGATION REQUIRED :默认值,如果A中有事务,使用A中的事务;如果A中没有事务,则创建一个新的事务,将操作包含进来;
2.1.2.保证多个操作不在同一个事务中
====PROPAGATION REQUIRES NEW : 如果A中有事务,将A的事务挂起(暂停),创建新的事务,只包含自身操作;如果A中没有事务,创建一个新事务,包含自身操作;
2.1.3.嵌套式事务
====PROPAGATION NESTED:嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作;如果没有异常,执行通过,若有异常可以选择回滚到最初始位置,也可以回滚到保存点

3.Spring事务管理的认识====模拟转账【未涉及事务】

3.1搭建Spring事务管理环境
1.引入必要的Jar包;
jdbc.properties的配置

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_1
jdbc.username=root
jdbc.password=123456

创建Service接口与实现
创建Dao的接口与实现
配置Service和Dao,交给Spring管理

/**
 * @author Leonard
 *	转账的业务层接口
 */
public interface AccountService {
	public void transfer(String from,String to,Double money);
}
/**
 * @author Leonard
 *	转账的业务层实现======无事务控制,出现异常,转账出现错误
 */
public class AccountServiceImpl implements AccountService {
	//1.注入Dao
	private AccountDao accountDao;

	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}

	@Override
	public void transfer(String from, String to, Double money) {
		accountDao.outMoney(from, money);//扣钱
		int b=1/0;//=================转账异常,程序终止
		accountDao.inMoney(to, money);//未收到钱
	}
}
/**
 * @author Leonard
 *	转账的Dao接口
 */
public interface AccountDao {
	/**
	 * @param from转出=========-钱
	 * @param money
	 */
	public void outMoney(String from,Double money);
	
	/**
	 * @param to转入=======+钱
	 * @param money
	 */
	public void inMoney(String to,Double money);
}

/**
 * @author Leonard
 *	Dao的实现类
 */
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

	/* (non-Javadoc)
	 * 转账扣钱
	 */
	@Override
	public void outMoney(String from, Double money) {
		this.getJdbcTemplate().update("update account set money=money-? where name=?" , money,from);
	}

	/* (non-Javadoc)
	 *	转账收钱
	 */
	@Override
	public void inMoney(String to, Double money) {
		this.getJdbcTemplate().update("update account set money=money+? where name=?", money,to);
	}

}

2.在xml中配置Service和Dao以及JDBC模板,交给Spring管理

<!--  配置Service -->
      <bean id="accountService" class="spring.tx.demo.AccountServiceImpl">
            <property name="accountDao" ref="accountDao"/>
      </bean>
      <!-- 配置Dao -->
      <bean id="accountDao" class="spring.tx.demo.AccountDaoImpl">
        <!-- 直接给Dao一个连接池即可 -->
            <property name="dataSource" ref="datasource"></property>
      </bean>
      <!-- 1.引入配置文件 -->
      <context:property-placeholder location="classpath:jdbc.properties"/>
      <!-- 2.引入相应的值 -->
      <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>

3.创建测试类操作数据库–模拟转账

/**
 * @author Leonard
 *	转账环境测试
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx.xml")
public class AccountTest {
	//创建业务层的类
	@Resource(name="accountService")
	private AccountService accountService;
	@Test
	public void demo(){
		accountService.transfer("bbb", "ccc", 100000d);
	}
}

4.Spring事务管理===第一类:编程式事务【了解】

1.配置平台事务管理器和事务管理模板类

<!--  配置平台事务管理器 -->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"></property>
      </bean>
 <!-- 配置事务管理模板 -->
      <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"/>
      </bean>

2.在业务层注入事务管理模板

<!--  配置Service -->
<bean id="accountService" class="spring.tx.demo.AccountServiceImpl">
      <property name="accountDao" ref="accountDao"/>
      <!-- 注入事务管理模板 -->
      <property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>

3.编写事务管理代码【了解】
对第三节中模拟转账中业务层实现进行升级,防止出现异常导致转账错误

/**
 * @author Leonard
 *	转账的业务层实现
 */
public class AccountServiceImpl implements AccountService {
	//1.注入Dao
	private AccountDao accountDao;

	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	//2.注入事务管理的模板
	private TransactionTemplate transactionTemplate;

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}


	@Override
	public void transfer(final String from, final String to, final Double money) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {//事务控制,出现异常,则不会转账成功
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
				accountDao.outMoney(from, money);
				int d = 1/0;//=========异常,事务回滚
				accountDao.inMoney(to, money);
			}
		});
	}
}

5.【重点】Spring事务管理===第二类:声明式事务管理(通过配置实现)–AOP思想

5.1xml方式
1.引入必要的jar
在这里插入图片描述
2.配置事务管理器和配置增强

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"></property>
</bean>
<!--  配置事务增强 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <tx:attributes>
       <tx:method name="transfer" propagation="REQUIRED"/>/*====为某个方法添加事务======*/
   </tx:attributes>
</tx:advice>

3.AOP配置

<!-- AOP配置 -->
<aop:config>
        <aop:pointcut expression="execution(* spring.tx.demo2.spring.tx.demo2.AccountServiceImpl.*(..))" id="pointcut1"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>

5.2注解方式===tx3.xml
1.配置事务管理器

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="datasource"></property>
</bean>

2.开启注解事务

<!--  开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

3.在业务层添加事务注解-----@Transactional
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)也可以添加隔离级别和传播行为

//添加注解
@Transactional
public class AccountServiceImpl implements AccountService {
	//1.注入Dao
	private AccountDao accountDao;

	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	@Override
	public void transfer(String from, String to, Double money) {
				accountDao.outMoney(from, money);
				int d = 1/0;//若没有事务控制会出现扣款成功,转账失败情况
				accountDao.inMoney(to, money);
			}
}

4.测试类测试,查询数据库前后对比

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx3.xml")
public class AccountTest {
	//创建业务层的类
	@Resource(name="accountService")
	private AccountService accountService;
	@Test
	public void demo(){
		accountService.transfer("bbb", "李四", 10000d);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值