范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Spring中的事务处理机制

  【1】事务管理
  事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性。
  事务就是一系列的动作, 它们被当做一个单独的工作单元。 这些动作要么全部完成, 要么全部不起作用。
  ① 事务的四个关键属性(ACID) 原子性(atomicity): 事务是一个原子操作, 由一系列动作组成。事务的原子性确保动作要么全部完成要么完全不起作用。一致性(consistency): 一旦所有事务动作完成, 事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中。隔离性(isolation): 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏。持久性(durability): 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响。通常情况下, 事务的结果被写到持久化存储器中。
  ① 原子性(atomicity)
  原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  事务是一个原子操作, 由一系列动作组成。 组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作执行成功,整个事务才提交。
  事务中的任何一个数据库操作失败,已经执行的任何操作都必须被撤销,让数据库返回初始状态。
  ② 一致性(consistency)
  事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
  一旦所有事务动作完成, 事务就被提交。数据和资源就处于一种满足业务规则的一致性状态,即数据不会被破坏。
  比如a+b=100,一个事务改变了a比如增加了a的值,那么必须同时改变b,保证在事务结束以后a+b=100依然成立,这就是一致性。
  ③ 隔离性(isolation)
  事务的隔离性是指 一个事务的执行不能被其他事务干扰  ,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。准 确地说,并非要求做到完全无干扰  。
  数据库规定了多种事务隔离界别,不同的隔离级别对应不用的干扰程度。隔离级别越高,数据一致性越好,但并发行越弱。比如对于A对B进行转账,A没把这个交易完成的时候,B是不知道A要给他转钱。
  ④ 持久性(durability)
  持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
  数据库管理系统一般采用 重执行 日志 来保证 原子性、一致性和持久性  。
  重执行日志记录了数据库变化的每一个动作,数据库在一个事务中执行一部分操作后发生错误退出,数据库即 可根据重执行日志撤销已经执行的操作  。对于已经提交的事务即使数据库崩溃,在重启数据库时也能根据日志对尚未持久化的数据进行相应的重执行操作。
  ② Spring 中的事务管理
  作为企业级应用程序框架, Spring 在不同的事务管理 API 之上定义了一个抽象层。 而应用程序开发人员不必了解底层的事务管理 API, 就可以使用 Spring 的事务管理机制。
  Spring 既支持编程式事务管理, 也支持声明式的事务管理。
  编程式事务管理
  将事务管理代码嵌入到业务方法中来控制事务的提交和回滚。在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码。编程式事务管理使用 TransactionTemplate  或者直接使用底层的 PlatformTransactionManager 。 对于编程式事务管理,spring推荐使用 TransactionTemplate 。
  声明式事务管理
  大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理。事务管理作为一种横切关注点, 可以通过 AOP 方法模块化。 Spring 通过 Spring AOP 框架支持声明式事务管理。
  声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于  @Transactional 注解  。显然基于注解的方式更简单易用,更清爽。
  Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
  ③ Spring 中的事务管理器
  Spring 的核心事务管理抽象是 org.springframework.transaction.PlatformTransactionManager  。
  它为事务管理封装了一组独立于技术的方法。无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的。
  ④ 事务属性
  事务管理器接口 PlatformTransactionManager  通过 getTransaction(TransactionDefinition definition)  方法来得到事务,这个方法里面的参数是TransactionDefinition 类,这个类就定义了一些基本的事务属性。
  那么什么是事务属性呢?事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面,如图所示:
  而 TransactionDefinition  接口内容如下:public interface TransactionDefinition {   int PROPAGATION_REQUIRED = 0;    int PROPAGATION_SUPPORTS = 1;    int PROPAGATION_MANDATORY = 2;    int PROPAGATION_REQUIRES_NEW = 3;    int PROPAGATION_NOT_SUPPORTED = 4;    int PROPAGATION_NEVER = 5;    int PROPAGATION_NESTED = 6;    int ISOLATION_DEFAULT = -1;    int ISOLATION_READ_UNCOMMITTED = 1;  // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;    int ISOLATION_READ_COMMITTED = 2;  // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;    int ISOLATION_REPEATABLE_READ = 4;  // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;    int ISOLATION_SERIALIZABLE = 8;  // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;    int TIMEOUT_DEFAULT = -1;    default int getPropagationBehavior() {     return PROPAGATION_REQUIRED;   }    default int getIsolationLevel() {     return ISOLATION_DEFAULT;   }    default int getTimeout() {     return TIMEOUT_DEFAULT;   }    default boolean isReadOnly() {     return false;   }    @Nullable   default String getName() {     return null;   }    static TransactionDefinition withDefaults() {     return StaticTransactionDefinition.INSTANCE;   } }
  【2】Spring中事务管理器
  ① 核心接口PlatformTransactionManager
  Spring事务管理器的接口是 org.springframework.transaction.PlatformTransactionManager , 通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
  PlatformTransactionManager接口的内容如下:public interface PlatformTransactionManager()  {     // 由TransactionDefinition得到TransactionStatus对象    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;     // 提交    Void commit(TransactionStatus status) throws TransactionException;      // 回滚    Void rollback(TransactionStatus status) throws TransactionException;    }
  从这里可知具体的具体的事务管理机制对Spring来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型,如 JTA、JDBC、Hibernate、JPA 。
  运行流程示例如下:
  ②几个事务管理器实现
  ① DataSourceTransactionManager
  在应用程序中只需要处理一个数据源,而且通过JDBC存取。如果应用程序中直接使用JDBC来进行持久化,DataSourceTransactionManager会为你处理事务边界。为了使用 DataSourceTransactionManager  ,你需要使用如下的XML将其装配到应用程序的上下文定义中:         
  实际上,DataSourceTransactionManager是通过调用java.sql.Connection来管理事务,而后者是通过DataSource获取到的。通过调用连接的commit()方法来提交事务,同样,事务失败则通过调用rollback()方法进行回滚。
  ② JpaTransactionManager
  Hibernate多年来一直是事实上的Java持久化标准,但是现在Java持久化API作为真正的Java持久化标准进入大家的视野。
  如果你计划使用JPA的话,那你需要使用 Spring JpaTransactionManager  来处理事务。你需要在Spring中这样配置JpaTransactionManager:    
  JpaTransactionManager  只需要装配一个JPA实体管理工厂( javax.persistence.EntityManagerFactory 接口的任意实现) 。 JpaTransactionManager  将与由工厂所产生的JPA EntityManager 合作来构建事务。
  ③ HibernateTransactionManager
  如果应用程序的持久化是通过 Hibernate  实现的,那么你需要使用 HibernateTransactionManager  。对于Hibernate3 ,需要在Spring 上下文定义中添加如下的   声明:      
  sessionFactory  属性需要装配一个 Hibernate  的 session  工厂, HibernateTransactionManager  的实现细节是它将事务管理的职责委托 org.hibernate.Transaction  对象,而后者是从 Hibernate Session  中获取到的。
  当事务成功完成时, HibernateTransactionManager  将会调用 Transaction  对象的 commit()  方法,反之,将会调用 rollback()  方法。
  ④ Java原生API事务
  如果你没有使用以上所述的事务管理,或者是跨越了多个事务管理源(比如两个或者是多个不同的数据源),你就需要使用 JtaTransactionManager  :    
  JtaTransactionManager  将事务管理的责任委托给 javax.transaction.UserTransaction  和
  javax.transaction.TransactionManager  对象,其中事务成功完成通 UserTransaction.commit()  方法提交,事务失败通过 UserTransaction.rollback()  方法回滚。
  【4】Spring声明式事务
  声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。
  ①
  事务管理是一种横切关注点     元素定义
  为了在 Spring 2.x 中启用声明式事务管理, 可以通过 tx Schema 中定义的     元素声明事务通知, 为此必须事先将这个 Schema 定义添加到     根元素中去。                      
  声明了事务通知后, 就需要将它与切入点关联起来.
  由于事务通知是在    元素外部声明的, 所以它无法直接与切入点产生关联. 所以必须在    元素中声明一个 aop:advisor  与切入点关联起来.
  由于 Spring AOP 是基于代理的方法, 所以只能增强公共方法. 因此, 只有公有方法才能通过 Spring AOP 进行事务管理。                                                                                              
  ② @Transactional注解
  在 Bean 配置文件中只需要启用     元素, 并为之指定事务管理器就可以了。如果事务处理器的名称是 transactionManager, 就可以在    元素中省略 transaction-manager 属性。这个元素会自动检测该名称的事务处理器。
  SpringBoot下则使用 @EnableTransactionManagement  启用注解式事务管理。
  @Transactional  ,这个注解添加到类上面,也可以添加方法上面…如果把这个注解添加类上面,这个类里面所有的方法都添加事务…如果把这个注解添加方法上面,为这个方法添加事务。
  事务注解源码如下所示,其可以定义在类或者方法上面。@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional {     // transactionManage的别名   @AliasFor("transactionManager")   String value() default "";     // 具体transaction的值,可能用来检测目标事务管理器   @AliasFor("value")   String transactionManager() default "";     // 事务传播行为   Propagation propagation() default Propagation.REQUIRED;     // 事务隔离级别,默认是Isolation#DEFAULT    //专门设计用于REQUIRED或者REQUIRES_NEW,因为其只适用于新启动的事务    //如果您希望隔离级别声明在参与具有不同隔离级别的现有事务时被拒绝,    //请考虑在事务管理器上切换"验证有效事务"标志为"true"。   Isolation isolation() default Isolation.DEFAULT;     //事务超时时间 单位秒 默认为基础事务系统的默认超时    //专门设计用于REQUIRED或者REQUIRES_NEW,因为其只适用于新启动的事务   int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;   // 默认为false。如果事务实际上是只读的允许设置为true,从而允许在运行时进行相应优化  //这只是作为实际事务子系统的提示;它不一定会导致写入访问尝试失败  //当请求只读事务时,无法处理只读提示的事务管理器将不会抛出异常,而是默默地忽略该提示。   boolean readOnly() default false;     // 定义0或多个异常类型标明这些异常类型会导致事务回滚    //默认情况下,事务将在{RuntimeException}和{Error}上回滚,    //但不会在已检查的异常(业务异常)上回滚。    // 与rollbackForClassName方法相比,该类在构造事务回滚规则上是首选方法   Class<? extends Throwable>[] rollbackFor() default {};     // 定义0或者多个异常类名称,标明这些异常一定导致事务回滚    // 这可以是完全限定类名的子字符串,目前不支持通配符    //例如ServletException可以支持javax.servlet.ServletException与子类   String[] rollbackForClassName() default {};     // 定义0或多个异常类型,标明这些异常不用事务回滚    // 与noRollbackForClassName相比,这是构造异常回滚规则的首选方法   Class<? extends Throwable>[] noRollbackFor() default {};     // 定义0或多个异常类名称,标明这些异常不用事务回滚   String[] noRollbackForClassName() default {};  }
  当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
  在项目中, @Transactional(rollbackFor=Exception.class)  ,如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
  在 @Transactional  注解中如果不配置rollbackFor属性,那么事物只会在遇到 RuntimeException和Error  的时候才会回滚,加上 rollbackFor=Exception.class , 可以让事物在遇到非运行时异常时也回滚。@Transactional(propagation=Propagation.REQUIRES_NEW,     isolation=Isolation.READ_COMMITTED,     rollbackFor={UserAccountException.class},     readOnly=false,     timeout=3) public void purchase(String userName, int isbn) { }
  超时和只读属性
  由于事务可以在行和表上获得锁, 因此长事务会占用资源, 并对整体性能产生影响。如果一个事物只读取数据但不做修改, 数据库引擎可以对这个事务进行优化。超时事务属性: 事务在强制回滚之前可以保持多久。这样可以防止长期运行的事务占用资源。超时属性以秒为单位计算。事务需要在一定时间内进行提交,如果不提交进行回滚。默认值是 -1 ,设置时间以秒单位进行计算。
  只读事务属性: 表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务。 readOnly:是否只读。读:查询操作,写:添加修改删除操作。readOnly默认值false,表示可以查询,可以添加修改删除操作。设置readOnly值是true,设置成true之后,只能查询。rollbackFor:回滚。设置出现哪些异常进行事务回滚noRollbackFor:不回滚。设置出现哪些异常不进行事务回滚
  【5】Spring中的事务传播行为
  当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播。例如: 方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在自己的事务中运行。事务的传播行为可以由传播属性指定,Spring 定义了 7 种类传播行为。
  MANDATORY表示强制性的,就是必须运行在事务内部。
  其中,最常使用的是 REQUIRED 、REQUIRES_NEW。
  前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的 DataSourceTransactionManager  )
  REQUIRES_NEW   启动一个新的, 不依赖于环境的 "内部" 事务。这个事务将被完全  commited   或  rolled back   而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等。 当内部事务开始执行时, 外部事务将被 挂起  , 内务事务结束时, 外部事务将继续 执行  。
  ① PROPAGATION_REQUIRED
  如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。//事务属性 PROPAGATION_REQUIRED methodA{ …… methodB(); …… } //事务属性 PROPAGATION_REQUIRED methodB{ …… }
  使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。
  单独调用methodB方法:main{   metodB(); }
  相当于Main{   Connection con=null;   try{     con = getConnection();     con.setAutoCommit(false);     //方法调用     methodB();     //提交事务     con.commit();   } Catch(RuntimeException ex) {     //回滚事务     con.rollback();   } finally {     //释放资源     closeCon();   } }
  Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务。
  单独调用MethodA时,在MethodA内又会调用MethodB。执行效果相当于:main{   Connection con = null;   try{     con = getConnection();     methodA();     con.commit();   } catch(RuntimeException ex) {     con.rollback();   } finally {     closeCon();   } }
  调用MethodA时,环境中没有事务,所以开启一个新的事务.当在MethodA中调用MethodB时,环境中已经有了一个事务,所以methodB就加入当前事务。
  ② PROPAGATION_SUPPORTS
  如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。//事务属性 PROPAGATION_REQUIRED methodA(){   methodB(); } //事务属性 PROPAGATION_SUPPORTS methodB(){ …… }
  单纯的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事务地执行。
  ③ PROPAGATION_MANDATORY
  如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。换句话说则是必须有一个存在事务能够让当前方法事务的执行,且自己不会开启事务。//事务属性 PROPAGATION_REQUIRED methodA(){   methodB(); } //事务属性 PROPAGATION_MANDATORY methodB(){ …… }
  当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常 throw new IllegalTransactionStateException("Transaction propagation ‘mandatory’ but no existing transactionfound");  当调用methodA时,methodB则加入到methodA的事务中,事务地执行。
  ④ PROPAGATION_REQUIRES_NEW
  总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。//事务属性 PROPAGATION_REQUIRED methodA(){   doSomeThingA();   methodB();   doSomeThingB(); } //事务属性 PROPAGATION_REQUIRES_NEW methodB(){ …… }
  调用A方法:main(){   methodA(); }
  相当于main(){   TransactionManager tm = null;   try{     //获得一个JTA事务管理器     tm = getTransactionManager();     tm.begin();//开启一个新的事务     Transaction ts1 = tm.getTransaction();     doSomeThing();     tm.suspend();//挂起当前事务     try{       tm.begin();//重新开启第二个事务       Transaction ts2 = tm.getTransaction();       methodB();       ts2.commit();//提交第二个事务     } Catch(RunTimeException ex) {       ts2.rollback();//回滚第二个事务     } finally {     //释放资源     }     //methodB执行完后,恢复第一个事务     tm.resume(ts1);     doSomeThingB();     ts1.commit();//提交第一个事务   } catch(RunTimeException ex) {     ts1.rollback();//回滚第一个事务   } finally {   //释放资源   } }
  在这里,我把ts1称为外层事务,ts2称为内层事务。从上面的代码可以看出,ts2与ts1是两个独立的事务,互不相干。Ts2是否成功并不依赖于 ts1。如果 methodA  方法在调用 methodB  方法后的 doSomeThingB  方法失败了,而 methodB  方法所做的结果依然被提交。而除了 methodB 之外的其它代码导致的结果却被回滚了。使用 PROPAGATION_REQUIRES_NEW  ,需要使用  JtaTransactionManager  作为事务管理器。
  ⑤ PROPAGATION_NOT_SUPPORTED
  总是非事务地执行,并挂起任何存在的事务。使用 PROPAGATION_NOT_SUPPORTED ,也需要使用JtaTransactionManager作为事务管理器。(代码示例同上,可同理推出)。
  ⑥ PROPAGATION_NEVER
  总是非事务地执行,如果存在一个活动事务,则抛出异常。其与 PROPAGATION_MANDATORY 是相反的。
  ⑦ PROPAGATION_NESTED
  如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务, 则按 TransactionDefinition.PROPAGATION_REQUIRED   属性执行。
  这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持 DataSourceTransactionManager  作为事务管理器。需要JDBC 驱动的 java.sql.Savepoint  类。
  有一些JTA的事务管理器实现可能也提供了同样的功能。使用 PROPAGATION_NESTED  ,还需要把 PlatformTransactionManage r 的 nestedTransactionAllowed  属性设为true;而  nestedTransactionAllowed  属性值默认为false。//事务属性 PROPAGATION_REQUIRED methodA(){   doSomeThingA();   methodB();   doSomeThingB(); } //事务属性 PROPAGATION_NESTED methodB(){ …… }
  如果单独调用methodB方法,则按REQUIRED属性执行。如果调用methodA方法,相当于下面的效果:main(){   Connection con = null;   Savepoint savepoint = null;   try{     con = getConnection();     con.setAutoCommit(false);     doSomeThingA();     savepoint = con2.setSavepoint();     try{       methodB();     } catch(RuntimeException ex) {       con.rollback(savepoint);     } finally {     //释放资源     }     doSomeThingB();     con.commit();   } catch(RuntimeException ex) {     con.rollback();   } finally {   //释放资源   } }
  当methodB方法调用之前,调用setSavepoint方法,保存当前的状态到savepoint。如果methodB方法调用失败,则恢复到之前保存的状态。但是需要注意的是,这时的事务并没有进行提交,如果后续的代码( doSomeThingB () 方法)调用失败,则回滚包括methodB方法的所有操作。
  嵌套事务一个非常重要的概念就是内层事务依赖于外层事务  。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
  PROPAGATION_NESTED   与 PROPAGATION_REQUIRES_NEW  的区别
  :它们非常类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。
  使用  PROPAGATION_REQUIRES_NEW  时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。
  使用 PROPAGATION_NESTED  时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务 DataSourceTransactionManager  使用 savepoint  支持 PROPAGATION_NESTED 时,需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的 JTA TrasactionManager  实现可能有不同的支持方式。
  PROPAGATION_REQUIRES_NEW   启动一个新的, 不依赖于环境的 "内部" 事务。 这个事务将被完全 commited  或  rolled back  而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等。 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行。
  另一方面,  PROPAGATION_NESTED   开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务。 嵌套事务开始执行时, 它将取得一个  savepoint 。如果这个嵌套事务失败, 我们将回滚到此  savepoint 。 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。
  由此可见,  PROPAGATION_REQUIRES_NEW   和  PROPAGATION_NESTED   的最大区别在于,
  PROPAGATION_REQUIRES_NEW   完全是一个新的事务, 而  PROPAGATION_NESTED   则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back。
  PROPAGATION_REQUIRED  应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。
  【6】事务的隔离级别
  从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题。 然而, 那样会对性能产生极大的影响, 因为事务必须按顺序运行。在实际开发中, 为了提升性能, 事务会以较低的隔离级别运行。事务的隔离级别可以通过隔离事务属性指定。
  事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持。
  Oracle 支持的2 种事务隔离级别: READ_COMMITTED, SERIALIZABLE  。Oracle 默认的事务隔离级别为:  READ_COMMITTED  。
  MySQL支持4 种事务隔离级别: READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE  。MySQL 默认的事务隔离级别为:  REPEATABLE_READ

又好看又能防丢,PebbleBeeClip支持苹果FindMy功能PebblebeeClip采用全黑色的塑料机身和全金属框架,以保持其安全性,并集成了LED,以帮助在黑暗的地方找到它。它的工作距离最远可达500英尺,有一个响亮的蜂鸣器,而且是防水预算两千左右!双11安卓手机怎么选?RedmiNote12探索版是最优选临近双十一,相信最近想换手机的盆友不在少数,为了帮助低预算购机的朋友更好地选到自己的梦中神机,小编对比了市面上多款两千元机型,最后还是给大家安利RedmiNote12探索版。在双十网络电视机,如何设置开机直接进入电视直播网络时代,现在家里几乎都是使用网络电视机,开机半天,都找不到电视台,操作之复杂,令家里的长辈及小朋友增添烦恼!如何开机即刻进入到电视播放界面呢?现在给大家介绍操作步骤,要用到2款A捡漏时代开始PS4原装手柄随着PS5时代的来临,PS4渐渐让出C位,但是也给了我们捡漏的机会。售价比原来低出很多。DualShock系列控制器以PlayStation4代结束,如果你一直在寻找DualSen羊了个羊大火后,上市公司大赚10亿,开发者卖股份买大平层羊了个羊大火,背后上市公司大赚,吉比特派发现金10。06亿。任何热搜,最后都能和A股扯上关系。羊了个羊盈利冲上热搜,豪横的是利润分配方案,分现金10个多亿。羊了个羊的模式,第一关傻黑猫奇闻社女人钱难赚啊,还是回归屌丝市场吧只要产品足够优秀,女人充值起来也令人发指。曾经问过一个长期徘徊在王者荣耀青铜3星段位的女玩家,你塔喵打的这么菜,花x万块钱买皮肤图个啥,您猜怎么着,她说,我虽然菜,但我死也要死的比传世无双散人传世天堂!复古微变三职业带元神传世无双是一款三端互通的传世手游,在原来传世基础上取消了所有地图的门槛限制,实现打宝自由,散人天堂!原班打造的复古传世手游,三端互通散人服,适合喜欢自由打宝PK的散人兄弟,接下来就玩了永劫无间,我的学历从大专变成了研究生在大多数人眼中,喜欢玩游戏,并且长时间投入到游戏中的人,成绩都不会特别好,学历自然也就一般。不过最近有网友发现,玩多人动作游戏永劫无间,竟然能让学历提升,很多玩家实现了专本连硕,这腐团儿晒异域风情照!一双大长腿沙发放不下,身材骨感比例不错小伙伴们大家好,又到了和大家分享游戏的时间了,最近这段时间王者荣耀非常给力,七周年的活动吸引了众多玩家围观,除此之外还推出了几款风格迥异的新皮肤,王昭君的星穹之声光影效果一绝,不知王者荣耀不知火舞新皮肤特效曝光,化身月妖携百妖同行王者荣耀将在本周举行七周年庆,不仅会上线鬼谷子的免费新皮肤,还将推出不知火舞的新皮肤绯月行,该皮肤已定于本周六上架,首周折扣1430点券。而今,这款皮肤的特效也已经公布,特效以赤红传承者加强版一款同时融入了美少女和机战要素的SRPG传承者加强版RelayerAdvanced是由DRAGAMIGAMES,LTD。制作发行的一款同时融入了美少女和机战要素的SRPG,本作主要讲述了觉醒了特殊能力的人类星之子(以姐姐
为什么酒要慢慢喝细细品酒要慢慢喝,细细品,这种细细品味慢慢感受的心境,正是很多人最稀缺的。快节奏的生活,是社会快速发展附带的产物,虽然带来了高效的生产力,却也给人们带来了更多压抑的情绪。不知从何时起,人被社会毒打之后的领悟被社会毒打之后的领悟一我时常觉得自己的人生,走了太多的弯路。生活之中,未遇高人指引,自己只是苦苦摸索之中前行,很多道理,懂得太晚了,错过很多的机会。一个人在青年时,有高人指路,或找良心是最好的评判官良心是做人的道德底线,是所有人都具备的,把良心用在对的地方,正义的地方,就能对得起自己的良心,否则,就对不起自己的良心。良心是最好的评判官,你可以欺骗别人,却永远欺骗不了自己,我们明天你好,11月13日历史上11月13日都发生了什么?354年奥古斯丁,古代基督教会最伟大的思想家出生。650年王勃,初唐著名诗人出生。1007年英格兰国王艾塞尔雷德二世下令屠杀在英格兰境内的丹麦人。1science重磅LHPsMOFs,实现重大突破一研究背景钙钛矿(perovskite)是德国矿物学家古斯塔夫罗斯(GustavRose)在1839年,于俄罗斯中部境内的乌拉尔山脉上发现钙钛矿岩石样本,决定以他心中伟大的地质学家电磁涡环光脉冲飞翔的斯格明子导读结构电磁波的操控不仅承载了人们对超快超强的信息与能量提取的终极梦想,也不断揭示着新的基础物理效应。现代光学中的拓扑结构,如电磁场中的奇异点,也一直是一个热门的话题。最近因凝聚态有人说我们永远也飞不出自己的母星,你有什么看法?有人说我们永远也飞不出自己的母星,你有什么看法?自1957年苏联发射第一颗人造地球卫星以来,人类先后朝太空发射了各种飞船探测器地球卫星,1969年,美国人率先登陆月球,这是人类第一闪迪至尊高速酷邃USB3。0闪存盘实测闪迪一贯的简约包装,红黑白配色,简单大方,透过包装可以直接看到优盘外貌。背面可以扫描二维码辨别真伪,正品拥有5年质保哦,根据以往的使用经验大部分也是直接换新。大文件读取速度基本都在华为曲线救国,解决5G芯片难题,海思麒麟不再是独家文谛林审核子扬校对知秋华为P50系列上市以来,国内消费者并没有因为华为在外部压力巨大的情况下,仍然维持智能手机业务的正常运营感到高兴,反而十分担心华为智能手机业务的处境。因为受到禁天冷,吃肉不如多吃它,才2元一斤,富含胶原蛋白,卤着吃最香天冷了,又到做香肠腊肉的时候了,最近猪肉13块钱一斤,灌香肠的人挺多的。我们家大人孩子都很爱吃香肠,所以我也买了10斤猪肉,拿去加工。排队买肉的时候,我发现灌香肠剩下的猪皮,很多人绿军还是那么吝啬,想换西蒙斯,塔图姆与布朗总要交易走一位绿军新赛季是苦不堪言,新阵容尽管有新势力,但是绿军的综合战力是在下降的,因此导致绿军连季后赛的门槛都有点摸不到的意思,按照目前状态发展,绿军只能将季后赛的希望寄托于附加赛,甚至可能