zoukankan      html  css  js  c++  java
  • 事务的基础入门


      大家在不知道事务这个东西的时候,会不会在自己的某一次报错中“灵机一动”的想到这样一个问题。银行、微信、支付宝在
    转账的过程中突然报错了,我的钱转过去了,而对方并没有收到我的钱。仔细想一想,那我是不是可以借着这个,来赢取白富美,
    走向人生巅峰,我先定他一个小目标......,直到在很久以前的某一天,我知道了事务这个东西,额......

    一、什么是事务

      事务是一个很广泛的词,各行各业对这个词都有不同的理解,而对于计算机术语而言,它则代表着Transaction - 就是逻辑上的
    一组操作,组成这组操作的各个单元要么全部成功,要么全都失败。在知道了事务的概念后,我还是晕晕的,满足什么样的特性
    才可以称的是事务呢?

    二、事物的四个特性

    * 原子性(A):不可分割  

     组成事务的所有逻辑上的操作,要不就全都执行,要不就一个都不要执行(生死与共)。

    * 一致性(C):事务在执行前后,要保证数据的一致

      一致性可以简单的理解为2个人转账,转账前和转账后的两人金钱总和,不发生改变。这个栗子只是在描述最后的结果,而产生一致
    性的原因,除了结果守恒以外还有些什么呢(数据库里是怎么保证一致性的)?存入数据库的数据,都是我们将现实里的东西,通过代码
    的方式进行抽象化。将抽象化对象中,我们所需要的属性值,存入到数据库中(数据化)。为了方便辨别和使用,我们会给这个属性取
    一个数据库里的名字(列名)。那么一个类的前后一致性一定是,这个类的所有根性都要前后一致,即 : 要保证实体完整性(主属性不
    为空)、参照完整性(外键必须存在原表中)、用户自定义的完整性(自己为这个类定义的一些约束)。

    * 隔离性(I):一个事务在执行的过程中,不应该受到其它事务的干扰

      隔离性依赖于加锁或者多版本控制,在执行了一条插入的SQL,如加上个100万。如果该事物没有提交,其他的事物是不能读到这条
    执行结果的。

    * 持久性(D):事务一旦结束,数据持久化到数据库

    三、事务的一些问题

      如果不考虑事务的隔离性的,会发生一些什么样的问题呢?

    * 脏读:         一个事务读取到另一个事务的未提交数据。

    * 不可重复读:  一个事务读取到另一个事务提交的数据(主要是指update),会导致两次读取的结果不一致。

    * 虚读(幻读): 一个事务读取到另一个事务提交的数据(主要是指insert),会导致两次读取结果不一致。

      以上的这些问题可能会导致许许多多的问题,那么它还有救么?我们可以通过设置不同的隔离级别,来解决脏读、
    不可重复读等问题。

    四、事物的隔离级别

      事务一空有四个隔离级别,分别是:

    * READ_UNCOMMITED 读取未提交,它引发所有的隔离问题。

    * READ_COMMITTED    读已提交,阻止脏读,可能发生不可重复读与虚读。

    * REPEATABLE_READ  重复读 阻止脏读,不可重复读 可能发生虚读。

    * SERIALIZABLE           串行化 解决所有问题 不允许两个事务,同时操作一个目标数据。(效率低下)

      而在常用的数据库中 ORACLE 的默认的是事务隔离级别是 READ_COMMITTED,MYSQL 默认的事务隔离级别 REPEATABLE_READ。

    五、Spring对事务管理的简单使用

      Spring框架的一大亮点就是他对事物的支持非常友好,使用起来也很方便,Spring的事务管理有着四个优点:

    * 提供一致的对于不同的事务管理的API

    * 支持声明式事务管理

    * 编程事务管理(使用较少)

    * 优秀的整合与Spring的数据访问   

      Spring的事务管理主要是通过3个接口来提供支持的:

    1、org.springframework.transaction.PlatformTransactionManager  

      这是一个事务管理器,可以来选择相关的平台(Jdbc、Hibernate、Jpa等),即:你要使用哪个平台的事务。

    2、TransactionDefinition   

      它定义事务的一些相关信息,例如:隔离、传播、超时、只读。
        * 隔离:设置事物的隔离级别,如:ISOLATION_READ_COMMITTED 可以解决脏读,会产生不可重复读与虚读。
        * 传播:它解决的是两个被事务管理的方法互相调用问题。是程序内部维护的问题。如:PROPAGATION_REQUIRED(默认值)
    两个操作处于同一个事务,如果之前没有事务,则新建一个事务。
        * 超时:默认值是-1,它使用的是数据库默认的超时时间。
        * 只读:它的值有两个true/false,如果选择true一般是在select操作时。

    3、TransactionStatus

       它定义了事务状态信息,在事务运行过程中,得到某个时间点的状态。

    (一)基于XML配置声明式事务

      在导入相关依赖之后还要在applicationContext.xml文件中添加aop与tx的名称空间。

    <!-- 引入外部的properties文件,数据库连接配置文件-->
    <context:property-placeholder location="classpath:db.properties" />
    
    <!-- 创建c3p0连接池,连接数据库 -->
    <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driverClass}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    </bean>
    
    <!-- service -->
    <bean id="accountService" class="cn.lalala.service.AccountServiceImpl">
    <!-- 引入Dao层依赖 -->
    <property name="accountDao" ref="accountDao"></property>
    </bean>
    
    <!-- dao dao层要继承JdbcDaoSupport类-->
    <bean id="accountDao" class="cn.lalala.dao.AccountDAOImpl">
    <!-- 当注入dataSource后,底层会自动创建一个JdbcTemplate模板类,详情可以参看JdbcDaoSupport类的源码-->
    <property name="dataSource" ref="c3p0DataSource" />
    </bean>
    
    <!-- 配置事务管理器,这里用的是jdbc的 -->
    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 要注入连接池,参数请看DataSourceTransactionManager的源码 -->
    <property name="dataSource" ref="c3p0DataSource"></property>
    </bean>
    
    <!-- 配置通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <!-- 
    name:    必须的 对哪些方法进行事务控制
    isolation 可选 设置事务隔离级别 默认是DEFAULT 
    propagation:    可选 设置事务传播 默认值 REQUIRED
    timeout 可选 超时时间 默认值-1 
    read-only 可选 默认值是false 如果不是只读,它可以对insert update delete操作,如果是只读不可以。
    rollback-for 可选 可以设置一个异常,如果产生这个异常,触发事务回滚
    no-rolback-for 可选 可以设置一个异常,如果产生这个异常,不会触发事务回滚
    -->
    
    <!-- 要被事务管理的方法 -->
    <tx:method name="account" />    
    </tx:attributes>
    </tx:advice>
    
    <!-- 配置切面 -->
    <aop:config>
    <!-- 配置切点 -->
    <aop:pointcut expression="execution(* cn.lalala.service.IAccountService.account(..))" id="txPointcut"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

    (二)基于注解配置事务

      在配置好事务管理器和开启注解式事务后,只需在被事务管理的方法或类(整个类下的所有方法)使用@Transactional注解。

    <!-- 开启注解式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

      注解式的配置和配置文件式的配置各有优缺点,注解式使用起来方便,但是不利于后期的维护,基于配置文件的则是配置
    起来比较麻烦但是方便阅读,容易理解。


  • 相关阅读:
    ExtJs系列教程
    linux 服务器时间 timedatectl命令时间时区操作详解
    aws CloudWatch Events
    AWS Shield
    aws ssm指令
    failed to set bridge addr: "cni0" already has an IP address different from 10.244.0.1/24
    AWS Systems Manager
    Amazon Inspector
    AWS 安全培训
    Amazon Inspector
  • 原文地址:https://www.cnblogs.com/0813lichenyu/p/8312515.html
Copyright © 2011-2022 走看看