栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > 架构设计

spring事务学习整理

架构设计 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring事务学习整理

Spring虽然提供了灵活方便的事务管理功能,但这些功能都是基于底层数据库本身的事务处理机制工作的。

一:数据库的四个特性


原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)和持久性(Durabiliy),简称ACID

二:数据并发问题

数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。这些问题可以归结为5类,包括3类数据读问题(脏读、不可重复读和幻象读)及2类数据更新问题(第一类丢失更新和第二类丢失更新)
①脏读
A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作。

②不可重复读
A事务读取了B事务已经提交的更改数据

③幻象读
A事务读取B事务提交的新增数据

幻象读和不可重复读是两个容易混淆的概念,前者是指读到了其他已经提交事务的新增数据,而后者是指读到了其他已经提交事务的更新数据
④第一类丢失更新
A事务撤销时,把已经提交的B事务的更新数据覆盖了

⑤第二类丢失更新
A事务覆盖B事务已经提交的数据

三:数据库锁机制

按锁对象的不同,一般可以分为表锁定和行锁定。从事务锁定的关系上看,可以分为共享锁定和独占锁定。共享锁定会防止独占锁定,但允许其他的共享锁定,而独占锁定既防止其他的独占锁,也防止其他的共享锁

四:事务隔离级别


事务的隔离级别和数据库的并发性是对立的。一般来说,使用READ UNCOMMITED隔离级别的数据库拥有最高的并发性和吞吐量,而是用SERIALIZABLE隔离级别的数据库并发性最低

五:ThreadLocal

ThreadLocal并不是一个线程,而是保存线程本地对象的容器。当运行多线程环境的某个对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的变量副本。所以每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。

一般情况下,只有无状态的Bean才可以在多线程环境下共享。在Sping中,绝大部分Bean都可以声明为singleton作用域,正因为spring对一些Bean中非线程安全的"状态性对象"采用ThreadLocal进行封装,让他们也成为线程安全的"状态性对象";

SimpleThreadLocal 的版本比较幼稚,但它和JDK所提供的ThreadLocal类在实现思路上是非常相近的:

package com.smart.transcation;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SimpleThreadLocal {
    private Map valueMap= Collections.synchronizedMap(new HashMap());

    public void set(Object newValue){
       valueMap.put(Thread.currentThread(),newValue);
    }

    public Object get(){
        Thread currentThread=Thread.currentThread();
        Object o=valueMap.get(currentThread);
        if(o==null && !valueMap.containsKey(currentThread)){
                o=initialValue();
                valueMap.put(currentThread,o);
        }
        return o;
    }

    public void remove(){
        valueMap.remove(Thread.currentThread());
    }

    public Object initialValue(){
        return null;
    }

}

ThreadLocal实例:

package com.smart.transcation;

public class SequenceNumber {
    private static ThreadLocal seqNum=new ThreadLocal(){
      public Integer initialValue(){
          return 0;
      }
    };

      public int getNextNum(){
          seqNum.set(seqNum.get()+1);
          return seqNum.get();
      }

      private static class  TestClient extends  Thread{
          private SequenceNumber sn;
          public TestClient(SequenceNumber sn){
              this.sn=sn;
          }

          public void run(){
              for(int i=0;i<3;i++){
                  System.out.println("thread["+Thread.currentThread().getName()+"]sn["+sn.getNextNum()+"]");
              }
          }
      }

      public static void main(String[] args){
          SequenceNumber sn=new SequenceNumber();
          TestClient tc1=new TestClient(sn);
          TestClient tc2=new TestClient(sn);
          TestClient tc3=new TestClient(sn);
          tc1.start();
          tc2.start();
          tc3.start();
      }
}

六:事务

事务管理器

事务同步管理器

当需要脱离模板类,手工操作底层持久化技术的远程API时,就需要通过这些工具类获取线程绑定的资源,而不应该直接从DataSource或SessionFactory中获取。因为后者不能获得与本线程相关的资源,因此无法让数据操作参与到与本线程相关的事务环境中

事务传播行为:

基于aop/tx命名空间配置事务

使用注解配置事务

@Transactional注解可以被应用于接口定义和接口方法、类定于和类的public方法上,@Transactional最好使用在业务实现类上

基于@Transactional注解的配置和基于XML的配置方式一样,它拥有一组普适性很强的默认事务属性,往往可以直接使用这些默认的属性:
事务传播性 :PROPAGATION_REQUIRED
事务隔离级别:ISOLATION_DEFAULT
读写事务实行:读/写事务
超时时间 :依赖于底层的事务系统的默认值
回滚设置 :任务运行期异常引发回滚,任务检查异常类型不会引发回滚

注意点–:
在相同线程中进行相互嵌套调用的事务工作在相同的事务中。如果这些相互嵌套调用的方法工作在不同的线程中,则不同线程下的事务方法工作在独立的事务中


基于接口动态代理的AOP事务增强来说,由于接口的方法必须是public的,这就要求实现类的方法必须是public,同时不能使用static修饰符

基于CGLib字节动态代理的方案是通过扩展被增强类,动态创建其子类的方式进行AOP增强织入的,由于使用final,static,privae修饰符的方法不能被子类覆盖,相应的这些方法无法实施AOP增强

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/912821.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号