Spring-声明式事务和事务细节

1.声明式事务:以前都是通过编程式事务,现在则只需要告诉Spring哪些是声明式事务即可

           事务管理代码的固定模式作为一种横切关注点,可以通过AOP方法模块化,进而借助AOP框架实现声明式事务管理。

            对于事务管理的方法(切面方法)不需要自己写,Spring会提供事务切面(事务管理器)

2.ResourceTransactionManager为一个接口,其子类中根据不同的框架选择不同的事务管理器

    该事务管理器可以在目标方法前后进行事务控制。

<?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: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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

<context:component-scan base-package="com.cuco"></context:component-scan>

<!-- 加载外部配置文件 固定写法classpath:表示引用类路径下的配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties"/>

<bean id="poolDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- ${}表示的就是动态取出配置文件中的value值 -->
<!-- 为了防止配置文件中的username和Spring中的属性值username冲突,因此将配置文件中的key值加上前缀 -->
<property name="user" value="${jdbc.username}" ></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>

<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="poolDataSource"></property>
</bean>

<!-- 事务控制 -->
<!-- 1.配置事务管理器让其进行事务控制 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<!-- 控制数据源 -->
	<property name="dataSource" ref="poolDataSource"></property>
</bean>

<!-- 开启基于注解的事务控制模式:依赖tx名称空间 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

<!-- 给事务方法加注解 -->

</beans>
@Service
public class BookService {
	@Autowired
	BookDao bookDao;
	@Transactional
	public void checkout(String username,String isbn){
		
		bookDao.updateStock(isbn);
		bookDao.updateBalance(username,bookDao.getPrice(isbn));
	}
}
@Repository
public class BookDao {
	
	@Autowired
	 JdbcTemplate jdbcTemplate;
	
	
	//减账户余额
	public void updateBalance(String userName,int price){
		String sql = "UPDATE account SET balance=balance-? WHERE username=?";
		jdbcTemplate.update(sql, price,userName);
		
	}
	
	//获取某本图书的价格
	public int getPrice(String isbn){
		String sql = "SELECT price FROM book WHERE isbn=?";
		return jdbcTemplate.queryForObject(sql, Integer.class,isbn);
		
	}
	
	//减库存
	public void updateStock(String isbn){
		String sql = "UPDATE book_stock SET stock=stock-1 WHERE isbn=?";
		jdbcTemplate.update(sql, isbn);
	}
	
	
}

事务细节

1.@Transactional中的属性

>isolation-Isolation:事务的隔离级别

>propagation-Propagation:事务的传播行为

>noRollbackFor-Class[]:哪些异常事务可以不回滚(可以让默认回滚的异常不回滚)

>noRollbackForClassName-String[]:

>roobackFor-Class[]:让原本不回滚的异常 指定让其回滚

>rollbackForClassName-String[]:

>readOnly-boolean:设置事务为只读事务:可以进行事务优化,加快查询速度,不需要管事务中的增删改等操作

>timeout-int:超时:事务超过指定执行时长后自动终止并回滚

异常分为运行时异常和编译时异常,运行时异常:可以不用处理,默认为回滚。 编译时异常:需要try-catch,或者throws,默认不回滚。

隔离级别:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会互相影响(以前因为并发问题会出现脏读、不可重复读、幻读的情况:脏读就是 修改数据但没有提交时被别人读出,最后事务发生回滚。不可重复读就是 两次读的值不一样。 幻读就是 每次读出的数据条数不同)

2.有事务的业务逻辑,容器中保存的是这个业务逻辑的代理对象

3.传播行为:当事务中嵌套事务时,当被嵌套的事务发生回滚时,可以设置嵌套在外面的事务是否发生回滚。

         当子事务设置为REQUIRED时,该子事务会服从外层事务,所有属性都继承外层事务的属性。(例如,子事务设置timeout时是失效的)

4.XML配置事务

<!-- 配置事务切面 -->
	<aop:config>
		<aop:pointcut 
			expression="execution(* com.atguigu.tx.component.service.BookShopServiceImpl.purchase(..))" 
			id="txPointCut"/>
		<!-- 将切入点表达式和事务属性配置关联到一起 -->
		<aop:advisor advice-ref="myTx" pointcut-ref="txPointCut"/>
	</aop:config>
	
	<!-- 配置基于XML的声明式事务  -->
	<tx:advice id="myTx" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 设置具体方法的事务属性 -->
			<tx:method name="find*" read-only="true"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="purchase" 
				isolation="READ_COMMITTED" 
	no-rollback-for="java.lang.ArithmeticException,java.lang.NullPointerException"
				propagation="REQUIRES_NEW"
				read-only="false"
				timeout="10"/>
		</tx:attributes>
	</tx:advice>
发布了27 篇原创文章 · 获赞 1 · 访问量 2016

猜你喜欢

转载自blog.csdn.net/yangyiyun199863/article/details/104951202