Spring事务

事务的作用:保持数据的一致性和完整性。

在学习数据库中,也到事务,只不过每个事务都需要,开启事务、提交事务、回滚事务、释放资源的代码,这种方式叫做“编程式事务管理”。

那么另一种事务管理方式,将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理,Spring声明式事务管理建立在AOP基础之上,是一个典型的横切关注点,通过环绕增强来实现,其原理是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完毕之后根据执行情况提交或回滚事务。这种方式是“声明式事务管理”。

如何使用声明式事务管理?

1、添加spring-aspects-4.3.10.RELEASE.jar包和aspectjweaver-x.x.x.jar包

2、在Spring配置文件中添加如下配置:

<context:component-scan base-package="com.jd"></context:component-scan>
	
	<bean id="datasource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" p:password="root" p:username="root">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"></property>
	</bean>

	<bean class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="datasource"></bean>
	
	<!-- 配置数据源事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="datasource"></property>
	</bean>
	<!-- 开启事务注解 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

3、在Service层public方法上添加事务注解——@Transactional

通过以下例子进行更好的理解:

背景:以下代码可以实现,钱够书够就可以“购买成功!”但是会出现书够钱不够的情况,此时也会对书籍表进行个更新!

@Service
public class CouponService implements ICouponService {

	@Autowired
	private CouponDao couponDao;
	@Autowired
	private BookDao bookDao;
	@Autowired
	private MoneyDao moneyDao;
	
	@Override
	public boolean insert(String userId, String bookId, int count){
		
		if(bookDao.enough(bookId, count)) {//书是否足够?updata
			bookDao.updata(bookId, count);
		}
		double price = bookDao.getPrice(bookId);
		double total = price * count;
		if(moneyDao.enough(userId, total)) {//钱是否足够?uodata
			moneyDao.updata(userId, total);
		}
		String id = UUID.randomUUID().toString();
		couponDao.insert(id, bookId, userId, total);
//
		return true;
	}

 

此时加上@Transcational注解,防止出现书够钱不够的情况:

书籍表中有10本书籍,每本书10元,一个人钱包有10元,欲买3本,则该行代码抛出MoneyException异常,但由于该异常为运行时异常,所以回滚事.

结果如下:

注意:

如果是检查时异常需要在@Transactional注解中添加了rollbackFor=MoneyException.class,才可以回滚事务!

 

timeout:设置一个事务所允许执行的最长时长(单位:秒),如果超过该时长且事务还没有完成,则自动回滚事务且出现org.springframework.transaction.TransactionTimedOutException异常.

代码改动如下:

	@Override
	@Transactional(timeout=3)
	public boolean insert(String userId, String bookId, int count){
		
		if(bookDao.enough(bookId, count)) {//书是否足够?updata
			bookDao.updata(bookId, count);
		}
		double price = bookDao.getPrice(bookId);
		double total = price * count;
		if(moneyDao.enough(userId, total)) {//钱是否足够?uodata
                //改动如下:延时4秒,但是timeout是3秒,所以会报异常
			try {
				Thread.sleep(4000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			moneyDao.updata(userId, total);
		}
		String id = UUID.randomUUID().toString();
		couponDao.insert(id, bookId, userId, total);
//
		return true;
	}

 

结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值