MyBatisjava版云笔记(七)之务管理

事务管理

事务:程序为确保工作处理的完整性,执行之等同漫漫或多修SQL语句。

事务管理:对作业中之SQL语句进行提交或者回滚。
物管理对于企业应用来说是任重而道远的,好只要出现异常情况,它吧可以保证数据的一致性,不生现脏数据。

  Spring Framework对事务管理提供了平的悬空,其特点如下:

  • 否歧之事务API提供平等的编程模型,比如JTA(Java Transaction API),
    JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)

  • 支撑声明式事务管理,特别是依据注解的声明式事务管理,简单容易用

  • 供于任何事务API如JTA更简单的编程式事务管理API

  • 以及spring数据访问抽象的无所不包集成

事务管理方式

  spring支持编程式事务管理和声明式事务管理两种艺术

  编程式事务管理运用TransactionTemplate或者直接利用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐以TransactionTemplate。

  声明式事务管理建立以AOP之上的。其实质是针对性法前后开展阻挠,然后在对象措施开始前创建或者投入一个业务,在尽了目标措施之后因实施情况提交或者回滚事务。声明式事务最充分之长处就是是未需要经编程的章程管理业务,这样便未待以事情逻辑代码中混杂事务管理的代码,只需要以布置文件中做连锁的事情规则声明(或者通过根据@Transactional注解的法子),便足以以事情规则以到工作逻辑中。

  明白声明式事务管理要优于编程式事务管理,这正是spring倡导之非侵入式的开发方式。声明式事务管理使工作代码不被污染,一个便的POJO对象,只要加上注解就得赢得完全的事体支持。和编程式事务相比,声明式事务唯一不足地方是,后者的太缜密粒度只能作用及艺术级别,无法形成像编程式事务那样好作用及代码片级别。但是就算有这般的要求,也有很多变更之章程,比如,可以以索要开展事务管理的代码块独立也艺术等等。

  声明式事务管理也出星星点点种植常用之计,

  •   一种是基于tx和aop名字空间的xml配置文件
  •   别一样种植就是是**基于@Transactional注解**。
    眼看基于注解的方式重新简便易行好用,更舒畅。

spring事务特性

  spring所部分事务管理策略类都蝉联自org.springframework.transaction.PlatformTransactionManager接口,其中TransactionDefinition接口定义以下特点:

事务隔离级别

  隔离级别是凭借多少独冒出的工作间的隔离程度。TransactionDefinition
接口中定义了五单象征隔离级别的常量:

  •   TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示用底层数据库的默认隔离级别。对多数数据库而言,通常就值就是是TransactionDefinition.ISOLATION_READ_COMMITTED。

  •   TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事情可以读取另一个事情修改只是尚并未交给的多少。该级别不能够预防污染读,不可再读与幻读,因此杀少使用该隔离级别。比如PostgreSQL实际上并没有这级别。

  •   TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个工作只能读取另一个工作都付诸的多少。该级别可以防范污染读,这也是大多数情下之推荐值。

  •   TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个政工在全体过程被可以多次重复执行有查询,并且每次回去的笔录还同样。该级别可以防止脏读和不可再读。

  •   TransactionDefinition.ISOLATION_SERIALIZABLE:所有的业务逐项逐个执行,这样工作中便全无容许有干扰,也就是说,该级别可以防水污染读、不可再读与幻读。但是就将严重影响程序的性。通常状态下吧无见面为此到该级别。

作业传播行为

  所谓事务的传播行为是依赖,如果于上马即事情之前,一个政工及下文已经是,此时发若干挑选可以指定一个事务性方法的行行为。在TransactionDefinition定义着包括了之类几个象征传播行为的常量:

  •   TransactionDefinition.PROPAGATION_REQUIRED:如果手上设有工作,则投入该事情;如果手上尚未事情,则创造一个新的作业。这是默认值。

  •   TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果手上存业务,则拿当下政工挂于。

  •   TransactionDefinition.PROPAGATION_SUPPORTS:如果手上设有工作,则投入该事务;如果手上莫事情,则以非事务的主意延续运行。

  •   TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果手上存工作,则将当前作业挂于。

  •   TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果手上存在业务,则弃来非常。

  •   TransactionDefinition.PROPAGATION_MANDATORY:如果手上是工作,则加入该工作;如果手上没有事情,则弃来很。

  •   TransactionDefinition.PROPAGATION_NESTED:如果手上存在工作,则创造一个政工作为当前工作的嵌套事务来运行;如果手上从未工作,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

事务超时

  所谓事务超时,就是据一个事务所允许实施之卓绝丰富日子,如果跨越该时间限制而工作还并未就,则自动回滚事务。在
TransactionDefinition 中盖 int 的值来表示过时间,其单位凡秒。

  默认设置为底色工作系统的超时值,如果底层数据库事务系统并未设置超时值,那么就是none,没有过限制。

工作只读属性

  只念事务用于客户代码只念而切莫修改数据的状,只念事务用于特定情景下的优化,比如利用Hibernate的早晚。

默认为念写作业。

  “只读事务”并无是一个要挟选项,它只有是一个“暗示”,提示数据库驱动程序和数据库系统,这个事情并无含反数据的操作,那么JDBC驱动程序和数据库就闹或根据这种气象对拖欠事情进行一些一定的优化,比方说勿安排相应的数据库锁,以减轻工作对数据库的下压力,毕竟事务也是只要吃数据库的资源的。

  但是你莫要是当“只读事务”里面修改数据,也毫无不可以,只不过对于数据一致性的保护非像“读写作业”那样保险而已。

  因此,“只读事务”仅仅是一个性优化的引荐配置而一度,并非强制你只要如此做不可

spring事务回滚规则

  指示spring事务管理器回滚一个事务之推介方式是以时下事情的上下文内抛来老。spring事务管理器会捕捉任何不处理的异常,然后根据规则决定是否回滚抛来怪的工作。

  默认配置下,spring只有在抛出的不胜与否运行时unchecked异常时才转滚该事情,也就是抛弃来之老大与否RuntimeException的子类(Errors也会造成事情回滚),而弃来checked异常则非会见招致业务回滚。可以显著的安排当抛出那些可怜时回滚事务,包括checked异常。也得明确定义那些老抛来时莫回滚事务。还足以编程性的通过setRollbackOnly()方法来指示一个业务必须回滚,在调用完setRollbackOnly()后若所能够尽的绝无仅有操作就回滚

根据声明式事务管理配置

  Spring的事务管理机制实现的法则,就是经如此一个动态代理对具有需要事务管理的Bean进行加载,并因部署于invoke方法被对当前调用的
方法名进行判断,并当method.invoke方法前后也那增长适量的事务管理代码,这样即使实现了Spring式的事务管理。Spring中之AOP实
现更为复杂和灵活,不过基本原理是相同的。

基于tx和aop配置

<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
        <!-- Spring 事务处理 -->
        <!-- 定义事务管理Bean -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dbcp"></property>
        </bean>
        <!--  配置事务传播特性 -->
        <tx:advice id="TestAdvice" transaction-manager="txManager">
            <tx:attributes>
              <tx:method name="save*" propagation="REQUIRED"/>
              <tx:method name="del*" propagation="REQUIRED"/>
              <tx:method name="update*" propagation="REQUIRED"/>
              <tx:method name="add*" propagation="REQUIRED"/>
              <tx:method name="find*" propagation="REQUIRED"/>
              <tx:method name="get*" propagation="REQUIRED"/>
              <tx:method name="apply*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

        <!--  配置参与事务的类 -->
        <aop:config>
        <aop:pointcut id="allTestServiceMethod" expression="execution(* com.test.testAda.test.model.service.*.*(..))"/>
        <aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />
        </aop:config>

注:

  (1)**
advice(建议)的命名:由于每个模块都见面起温馨的Advice,所以于命名上急需作出规范,初步的构想就是模块名+Advice**(只是一种命名规范)。

  (2) tx:attribute签所安排的凡当事务之点子的命名类型

<tx:method name="save*" propagation="REQUIRED"/>

  其中*呢过渡配符,即表示因save为开端的兼具方,即意味着可这命名规则的法作为一个业务。

  propagation=”REQUIRED”代表支持即政工,如果手上未曾事情,就新建一个工作。这是最为普遍的选项。

  (3)
aop:pointcut签配置与业务之类似,由于是在Service中开展数据库业务操作,配之该是带有那些当工作的点子的Service类。

  首先应特别注意的是id的命名,同样由每个模块都产生温馨事务切面,所以我以为始于的命名规则为
all+模块名+ServiceMethod。而且每个模块之间不同之处还在以下一句子:

  expression="execution(* com.test.testAda.test.model.service.*.*(..))"

  其中第一独表示回到值,第二代表service下子包,第三个*代表办法名,“(..)”代表法参数。

  (4)
aop:advisor标签便是把上面我们所安排的事务管理两有些属性整合起来作为周事务管理。

冲注解的声明式事务管理(@Transactional)

<!-- Spring 事务处理 -->
        <!-- 定义事务管理Bean -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dbcp"></property>
        </bean>
        <!-- 开启@Transactional -->
        <tx:annotation-driven transaction-manager="txManager"/>

  MyBatis自动参与届spring事务管理中,无需额外部署,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。

@Transactional属性

属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组

用法

   @Transactional
可以作用被接口、接口方法、类与近似方式及。当作用被类及时常,该类的持有
public
方法将都怀有该档的事务属性,同时,我们啊可以点子级别下该标注来覆盖类级别之概念。

  虽然 @Transactional
注解可以作用为接口、接口方法、类及近似措施上,但是 Spring
建议并非当接口或者接口方法及以该注解,因为当时只有在以基于接口的代办时其才会立竿见影。另外,
@Transactional 注解应该单独吃使用到 public 方法上,这是由 Spring AOP
的精神决定的。如果你当** protected、private
或者默认可见性的点子上使用 @Transactional
注解,
立将让忽略,也非会见丢弃来其他异常**。

   默认情况下,只有来自外部的道调用才见面给AOP代理捕获,也便是,类中方法调用本类内部的其余方法并无见面唤起事务行为,即受调用方法以@Transactional注解进行修饰。

@Service("userService")//扫描到spring容器

public class UserServiceImpl implements UserService{
    @Resource//注入dao对象
    private UserDao dao;

    @Transactional
    public void insert(User user) {  
        dao.insert(user);  
        throw new RuntimeException("user");//抛出unchecked异常,触发事物,回滚  
    } 
} 

    @Transactional(noRollbackFor=RuntimeException.class)  
    public void insert(User user) {  
        dao.insert(user);  
        //抛出unchecked异常,触发事物,noRollbackFor=RuntimeException.class,不回滚 
        throw new RuntimeException("user");
    } 

好像,当作用被类及时,该类的兼具 public 方法将还独具该类型的工作属性

@Service("userService")//扫描到spring容器
@Transactional
public class UserServiceImpl implements UserService{
    @Resource//注入dao对象
    private UserDao dao;

    public void insert(User user) {  
        dao.insert(user);  
        throw new RuntimeException("user");//抛出unchecked异常,触发事物,回滚  
    } 
} 

因非事务方式运行

@Transactional(propagation=Propagation.NOT_SUPPORTED)  
public void insert(User user) {  
    //事物传播行为是PROPAGATION_NOT_SUPPORTED,以非事务方式运行,不会存入数据库  
    dao.insert(user);  
} 
网站地图xml地图