事务@Transactional注解的属性
事务的传播⾏为
当事务⽅法被另⼀个事务⽅法调⽤时,必须指定事务应该如何传播。例如:⽅法可能继续在现有事务中运⾏,也可能开启⼀个新事务,并在⾃⼰的事务中运⾏。
事务的传播⾏为可以由传播属性指定。Spring定义了7种类传播⾏为。
事务传播属性可以在@Transactional注解的propagation属性中定义。
1) . 说明
  ①REQUIRED传播⾏为
当bookService的purchase()⽅法被另⼀个事务⽅法checkout()调⽤时,它默认会在现有的事务内运⾏。这个默认的传播⾏为就是REQUIRED。因此在checkout()⽅法的开始和终⽌边界内只有⼀个事务。这个事务只在checkout()⽅法结束的时候被提交,结果⽤户⼀本书都买不了。
②. REQUIRES_NEW传播⾏为
表⽰该⽅法必须启动⼀个新事务,并在⾃⼰的事务内运⾏。如果有事务在运⾏,就应该先挂起它。
事务的隔离级别
1、数据库事务并发问题
  假设现在有两个事务:Transaction01和Transaction02并发执⾏。
  1) 脏读(针对⼀条数据中的⼀个字段)
    ①Transaction01将某条记录的AGE值从20修改为30。
    ②Transaction02读取了Transaction01更新后的值:30。
    ③Transaction01回滚,AGE值恢复到了20。
    ④Transaction02读取到的30就是⼀个⽆效的值。
  2) 不可重复读(针对⼀条数据中的⼀个字段)
    ①Transaction01读取了AGE值为20。
    ②Transaction02将AGE值修改为30。
    ③Transaction01再次读取AGE值为30,和第⼀次读取不⼀致。
  3)幻读(针对表中的⼀⾏数据⽽⾔)
    ①Transaction01读取了STUDENT表中的⼀部分数据。
    ②Transaction02向STUDENT表中插⼊了新的⾏。
    ③Transaction01读取了STUDENT表时,多出了⼀些⾏。
2、隔离级别
数据库系统必须具有隔离并发运⾏各个事务的能⼒,使它们不会相互影响,避免各种并发问题。⼀个事
务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的⼲扰程度,隔离级别越⾼,数据⼀致性就越好,但并发性越弱。
  1) 读未提交:READ UNCOMMITTED
    允许Transaction01读取Transaction02未提交的修改。
  2) 读已提交:READ COMMITTED
     要求Transaction01只能读取Transaction02已提交的修改。
  3) 可重复读:REPEATABLE READ
   确保Transaction01可以多次从⼀个字段中读取到相同的值,即Transaction01执⾏期间禁⽌其它事务对这个字段进⾏更新。
  4) 串⾏化:SERIALIZABLE
    确保Transaction01可以多次从⼀个表中读取到相同的⾏,在Transaction01执⾏期间,禁⽌其它事务对这个表进⾏添加、更新、删除操作。可以避免任何并发问题,但性能⼗分低下。(单线程,在⼀个请求中,其他线程读都不可以)
⽤@Transactional注解声明式地管理事务时可以在@Transactional的isolation属性中设置隔离级别。
触发事务回滚的异常
1、默认情况
捕获到RuntimeException或Error时回滚,⽽捕获到编译时异常不回滚。
2、设置途经
1) 注解@Transactional 注解
① rollbackFor属性:指定遇到时必须进⾏回滚的异常类型,可以为多个
② noRollbackFor属性:指定遇到时不回滚的异常类型,可以为多个
事务的超时和只读属性
1、简介
由于事务可以在⾏和表上获得锁,因此长事务会占⽤资源,并对整体性能产⽣影响。如果⼀个事务只读
取数据但不做修改,数据库引擎可以对这个事务进⾏优化。
超时事务属性:事务在强制回滚之前可以保持多久。这样可以防⽌长期运⾏的事务占⽤资源。
只读事务属性: 表⽰这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务。
2、注解设置
@Transaction注解
package com.atguigu.book.service.impl;
import org.springframework.beans.factory.annotation.Autowired;springframework事务
import org.springframework.stereotype.Service;
import ansaction.annotation.Isolation;
import ansaction.annotation.Propagation;
import ansaction.annotation.Transactional;
import com.atguigu.book.dao.BookDao;
import com.ption.MyException;
import com.atguigu.book.service.BookService;
@Service
//@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookDao dao;
/
**
* @Transactional:对⽅法中所有的操作作为⼀个事务进⾏管理
* 在⽅法上使⽤,只对⽅法有效果
* 在类上使⽤,对类中所有的⽅法都有效果
* @Transactional中可以设置的属性:
*
* propagation:A⽅法和B⽅法都有事务,当A在调⽤B时,会将A中的事务传播给B⽅法,B⽅法对于事务的处理⽅式就是事务的传播⾏为
*        Propagation.REQUIRED:必须使⽤调⽤者的事务(默认值)
*        Propagation.REQUIRES_NEW:将调⽤者的事务挂起,不使⽤调⽤者的事务,使⽤新的事务进⾏处理
*
* isolation:事务的隔离级别,在并发的情况下,操作数据的⼀种规定
*            读未提交:脏读  1
*            读已提交:不可重复读  2
*            可重复读:幻读  4
*            串⾏化:性能低,消耗⼤  8
*
*
* timeout:在事务强制回滚前最多可以执⾏(等待)的时间
*
* readOnly:指定当前事务中的⼀系列的操作是否为只读
* 若设置为只读,不管事务中有没有写的操作,mysql都会在请求访问数据的时候,不加锁,提⾼性能
* 但是如果有写操作的情况,建议⼀定不能设置只读
*
* rollbackFor|rollbackForClassName|noRollbackFor|noRollbackForClassName:设置事务回滚的条件
*/
@Transactional(propagation=Propagation.REQUIRES_NEW, timeout=3, noRollbackFor= {NullPointerException.class, MyException.class}) public void buyBook(String bid, String uid) {
/*try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
Integer price = dao.selectPrice(bid);
dao.updateSt(bid);
dao.updateBalance(uid, price);
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。