详述Spring 框架事务 为什么 怎么做 @Transactional常用属性说明

Spring框架框架事务:

        为什么?

package club.shaoyu.coupon.service;

import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import club.shaoyu.book.dao.BookDao;
import club.shaoyu.coupon.dao.CouponDao;
import club.shaoyu.exception.UpdateException;
import club.shaoyu.money.dao.MoneyDao;
import club.shaoyu.vo.Coupon;

@Service
public class CouponService implements ICouponService {

	@Autowired
	private BookDao bookDao;
	@Autowired
	private MoneyDao moneyDao;
	@Autowired
	private CouponDao couponDao;
	
	@Override
	@Transactional
	public boolean insert(String bookId, String userId, int count) {
			if(bookDao.enough(bookId, count)) {
				try {
					bookDao.update(bookId, count);
				} catch (UpdateException e) {
					e.printStackTrace();
				}
			}
			float price =bookDao.getPrice(bookId);
			float totle=price*count;
			if(moneyDao.enough(userId, totle)) {
					Coupon coupon=new Coupon();
					coupon.setId(UUID.randomUUID().toString());
					coupon.setBookId(bookId);
					coupon.setUserId(userId);
					coupon.setTotle(totle);
					couponDao.insert(coupon);
					moneyDao.update(userId, totle);
			}
		return true;
	}
}

如图所示:我们在使用上述insert代码对数据库进行修改时,不难发现-->如果数据查询满足要求,但是钱包不够,此时仅仅可以将书籍修改,从而异常抛出-->为了解决上述问题-->我们使用Spring中的事务框架进行修改,达到的结果-->除非无异常抛出,其他的情况下均会使事务回滚,从而达到办公的要求

        @Transactional配置

一、是什么

@Transactional注解修饰的方法中会自动形成代理类并且形成上述Spring事务机制

二、怎么配置?

<?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:p="http://www.springframework.org/schema/p"
	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.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
		<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/userinfo"></property>
		<property name="username" value="root"></property>
		<property name="password" value="root"></property>
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
	</bean>
	<context:component-scan base-package="club.shaoyu"></context:component-scan>
	<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"/>
</beans>

    在Spring中如下配置,与连接数据库配置多了transactionManager类和annotation-driven标签进行驱动

    相应的jar包:

    将此形成代理类的包引入:spring-aspects-4.3.10.RELEASE.jar

    同时Spring相关和数据连接池相关的以及log4j引入即可

三、怎么做?

    @Transactional(属性=数值)

       timeout属性和readOnly

           在timeout中的方法为描述,若是对应的方法在三秒钟不执行结束,那么指定不执行

          如果想测试,大可将Thread.sleep(20000)添加代码中

              输出的结果为:Transaction timed out: deadline was Thu Mar 19 18:26:35 CST 2020

         readOnly

          只读操作是不可以对数据进项修改,否则报错

            输出异常:Connection is read-only

       rollbackFor和rollbackForClassName

            前提:定对哪些异常回滚事务。默认情况下,如果在事务中抛出了运行时异常(继承自RuntimeException异常类),则回滚事务;如果没有抛出任何异常,或者抛出了检查时异常,则依然提交事务,这告诉我们要想回滚相应异常或者是不会滚异常,我们需要相应的属性进行控制

        rollbackFor=检查时异常类便可:、

     事物的传播级别:

          propagation:正常情况下-->假设一个事务中的中有方法去调用另外一个事务,那么另外这个事务如何创建?这便涉及到事物的传播机制问题        

               REQUIRED:默认值,如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行

               REQUIRES_NEW:当前方法必须启动新事务,并在它自己的事务内运行,如果有事务在运行,则把当前事务挂起,直到新的事务提交或者回滚才恢复执行

        此时若是在一个事务中调用一个事物多次,默认情况下其中一个子事务失败,则全部失败,若是第二种的话便会发生一个事物下的事务单独执行

               

     isolation:指定事务隔离级别,Spring定义了如下5种事务隔离级别:

        DEFAULT:默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常为READ_COMMITTED。

        READ_UNCOMMITTED:表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别可能出现脏读、不可重复读或幻读,因此很少使用该隔离级别。

        READ_COMMITTED:表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,但可能出现不可重复读或幻读,这也是大多数情况下的推荐值。

        REPEATABLE_READ:表示一个事务在整个过程中可以多次重复执行某个查询,且每次返回的记录都相同,除非数据被当前事务自生修改。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读,但可能出现幻读。

        SERIALIZABLE:表示所有的事务依次逐个执行,事务之间互不干扰,该级别可以防止脏读、不可重复读和幻读,但是这将严重影响程序的性能,因此通常情况下也不会用到该级别。

        当多个事务同时发生,此时会发生多重不必要的行为,为了避免这些行为,我们采用上述方法将数据进行隔离,这些内容在前面的SQL中的事务隔离级别中也讲过

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值