Hibernate事务相关内容:

  (1) 事务四大特性(简称ACID):

    (1)原子性(Atomicity)
      事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
    (2)一致性(Consistency)
      几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

    (3)隔离性(Isolation)
      事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
    (4)持久性(Durability)
      对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

  (2) 事务并发执行时会出现的四大问题:

    (1) 更新丢失,又分为两类:

      (1)回滚更新丢失:

        A、B事务同时读取某数据,并均做修改。A事务先做了提交,而B事务又做回滚。此时,A事务提交的更新数据丢失。

        对应实例:回滚更新丢失在一般的数据库中不会存在,因为数据库最低的事务隔离级别已经解决了这个问题。

      (2)提交更新丢失:

        A、B事务同时读取某数据,并均做修改。A事务先做了提交,然后B事务也做提交。此时,A事务提交的更新数据会被B事务的提交给覆盖。

        对应实例:

         1. 假设当当网上用户下单买了本书,这时数据库中有条订单号为 001的订单,其中有个status字段是’有效’,表示该订单是有效的;
           2. 后台管理人员查询到这条001的订单,并且看到状态是有效的
           3. 用户发现下单的时候下错了,于是撤销订单,假设运行这样一条 SQL: update order_table set status = ‘取消’ where order_id = 001;
           4. 后台管理人员由于在2这步看到状态有效的,这时,虽然用户在3 这步已经撤销了订单,可是管理人员并未刷新界面,看到的订单状态还是有效的,于是点击”发货”按钮,将该订单发到物流部门,同时运行类似如下SQL,将订单状态改成已发货:update order_table set status = ‘已发货’ where order_id = 001
         

         如果当当的系统这样实现,显然不对了,肯定要挨骂了,明明已经取消了订单,为什么还会发货呢?而且确实取消订单的操作发生在发货操作之前啊。 因为在这样的实现下,后台管理人员无论怎么做都有可能会出错,因为他打开系统看到有效的订单和他点发货之间肯定有个时间差,在这个时间差的时候总是存在用户取消订单的可能。

    (2)脏读:

      即读取到不正确的数据,因为A事务可能还没提交最终数据,B事务就读取了中途的数据,一旦A事务回滚了,这个数据就是是不正确的。

      对应示例: 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。

    (3)不可重复读:

      A事务读取某一数据后,B事务对其做了修改,当A事务再次读该数据时得到与前一次不同的值。

      对应示例: singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......

    (4)幻读:

      A事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据。这是因为在两次查询过程中有B事务插入数据造成的。

      对应示例:singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

  (3)事务隔离级别及对应会出现的问题:

    (1)Read uncommitted(未授权读取、读未提交):

      写事务阻止其他写事务,但是没有阻止其他读事务。避免了回滚更新丢失,却可能出现脏读。

    (2)Read committed(授权读取、读提交):

      写事务会阻止其他读写事务。读事务不会阻止其他任何事务。避免了脏读,但是却可能出现不可重复读。

    (3)Repeatable read(可重复读取):

      读事务会阻止其他写事务,但是不会阻止其他读事务。避免了不可重复读和脏读,但是有时可能出现幻读。

      可重复读阻止的写事务包括update和delete(只给存在的表加上了锁),但是不包括insert(新行不存在,所以没有办法加锁),所以一个事务第一次读取可能读取到了10条记录,但是第二次可能读取到11条,这就是幻读。

    (4)Serializable(序列化):

      提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

      序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。

    大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。
    MYSQL的默认隔离级别就是Repeatable read。

   (4)提交更新丢失问题的解决:

     方法一,使用乐观锁(含义:这样的问题是小概率的,最后一步做更新的时候再锁住,免得锁住时间太长影响其他人做有关操作):

      乐观锁使用方法一:很简单,就是使用前面所说的这样一条SQL,这其实是所谓使用”前镜像”的方式来保证需要更新的数据是符合要求的,
        update order_table set status = ‘已发货’ where order_id = 001 and status = ‘有效’
      乐观锁使用方法二:使用版本列[比如时间戳或版本号]
        时间戳:这个方法比较简单,也最常用,就是在数据库表格中加一列last_modified_date,就是最后更新的时间,每次用户端更新的时候都将这列设成 systimestamp,当前系统时间;
        然后每次服务端更新的时候,就改成这样 update order_table set status = ‘已发货’ where order_id = 001 and last_modified_date = old (上次查看时的系统时间),last_modified_date这样,就可以检验出数据库的值是否在上次查看和这次更新的时候发生了变化,如果发生了变化,那么last_modified_date就变化了,以后的更新就会返回更新了0行,系统就可以通知用户数据发生了变化,然后选择刷新数据或者其他流程。

        版本号:用户端和服务端事务从数据库中读取数据时同时会读出一个数据版本号。当用户端事务将修改过的数据写入到数据库中时,会使版本号增1。当服务端事务发生回滚或覆盖时,会首先对比自己数据的版本号与数据库中数据的版本号。若它们相等,则说明数据库中数据没有发生变化,服务端事务可以将数据将修改写入到数据中。若小于数据库中的版本号,则说明用户端事务已经修改过该数据,将抛出异常。
    方法二,使用悲观锁(含义:这样的问题是高概率的,最好一开始就锁住,免得像使用乐观锁的时候,更新老是失败):

      服务端查询一条记录,并试图后续要做更新的时候,那么在查询的时候使用select *** for update nowait 语句,通过添加for update nowait语句,将这条记录锁住,避免其他用户更新,从而保证后续的更新是在正确的状态下更新的。

      但是存在一个问题:如果打开页面做查询的时候就将记录锁住,并且保持这个连接,那对连接的占用太长了,整个系统能承受的并发量就很小了。以oracle 10g为例,默认情况下,最大连接数是150,也就是说最多只能承受150个用户同时访问了。

    方法选择:乐观锁会导致更新失败频繁,悲观锁会降低并发性能。所以,一般在更新频繁的状况中使用悲观锁,其他情况用乐观锁较好。

  (5)Hibernate代码:

    (1)设置Hibernate事务隔离级别:

      在Hibernate的配置文件中可以显示的配置数据库事务隔离级别。每一个隔离级别用一个整数表示:

        8 - Serializable 串行化
        4 - Repeatable Read 可重复读
        2 - Read Commited 可读已提交
        1 - Read Uncommited 可读未提交

      在hibernate.cfg.xml中使用hibernate.connection.isolation参数配置数据库事务隔离级别。

    (2)乐观锁代码:

      在Hibernate映射文件的<class/>标签中,有一个子标签<version/>,其name属性用于指定作为版本的属性名称。其还有一个子标签<timestamp/>用于指定作为时间戳的属性名称。

      这两个子标签的用法相同,不同的是,作为版本的属性要求其类型为int,而作为时间戳的属性,要求为其类型为java.sql.timestamp。

      例如映射文件中是<version name="version" column="tversion"/>,则实体类中定义一个属性private int version;

      其他的事情由系统自己维护。

    (3)悲观锁代码:

      在测试代码中锁定,不需要修改实体类:

 @Test
public void test01_SQL() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
//悲观锁中的写锁
//Student student = session.get(Student.class, 2, LockMode.PESSIMISTIC_WRITE);
//悲观锁中的读锁
Student student = session.get(Student.class, 2, LockMode.PESSIMISTIC_READ);
System.out.println(student);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
}

      session.get方法的第三个参数就是用来设置悲观锁的,使用第三个参数之后,我们每次发送的SQL语句都会加上"for update"用于告诉数据库锁定相关数据。

Hibernate5笔记8--Hibernate事务相关内容的更多相关文章

  1. MySQL学习笔记-事务相关话题

    事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...

  2. 学习笔记之html5相关内容

    写一下昨天学习的html5的相关内容,首先谈下初次接触html5的感受.以前总是听说html5是如何的强大,如何的将要改变世界.总是充满了神秘感.首先来谈一下我接触的第一个属性是  input的里面的 ...

  3. Hibernate 事务和并发控制

    首先关于Hibernate事务控制,下面是非常权威的资料, https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch02.html ...

  4. Spring的事务管理和数据库事务相关知识

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱.         比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱. ...

  5. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  6. linux用户权限相关内容查看

    linux用户权限相关内容查看 1   用户信息 创建用户一个名为 webuser 的账号,并填写相应的信息: root@iZ94fabhqhuZ:~# adduser webuser Adding ...

  7. (转)Hibernate事务管理

    Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...

  8. hibernate学习笔记之一 hibernate简介

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架 hibernate可以自动生成SQL语句,自 ...

  9. hibernate事务

    hibernate事务 9.3 Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改 ...

随机推荐

  1. ios开发之 -- xib关联自定义view

    在xib下使用自定义的view,因为很多时候,可能幸亏自顶一个view,然后在view里面填充控件,但是需要重写很多无用的 代码,而且很容易出错不说,还很好工作量,使用xib的话,分钟搞定一个view ...

  2. BZOJ 3143 游走(贪心+期望+高斯消元)

    一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...

  3. Qt——基本工具的使用

    本文主要介绍在windows系统中使用C++编写Qt程序所需要的一些工具,不会具体地讲工具怎么使用. 其它系统的安装本文不会涉及,在http://wiki.qt.io/Main中,有关于各种系统qt安 ...

  4. 【Java】提取JSON数值时遇到数组集合时使用的K-V方式转换

    1.实体类转换方法 参照文章:http://www.cnblogs.com/dflmg/p/6933811.html 2.K-V方法(此方法比较笨,但是没有办法,我现在不知道有没有相关的简单API,只 ...

  5. JAVA相关概念(一)

    依赖注入和控制反转 首先,这两个词是同一个概念的不同角度的说法,依赖注入感觉是对描述了如何实现,而控制反转则像是描述了一种思想. 依赖注入的流行可以说是由spring的流行带动的,只要是做过sprin ...

  6. BZOJ5323 JXOI2018游戏(线性筛+组合数学)

    可以发现这个过程非常类似埃氏筛,将在该区间内没有约数的数定义为质数,那么也就是求每种方案中选完所有质数的最早时间之和. 于是先求出上述定义中的质数个数,线性筛即可.然后对每个最短时间求方案数,非常显然 ...

  7. 记一个鼠标略过时候的css动画

    .circle{ width: 15px; height: 15px; background: rgba(0,0,0,0.7); border-radius: 50%; display: table- ...

  8. H5页面遮罩弹框下层还能滚动的问题

    在页面上显示一个遮罩层,这是非常常见的操作,在遮罩层上操作,下层也会默认跟随手指滚动 此处就是要在显示遮罩的时候禁止下层滚动. 首先设置一个全局变量 var canScroll=false; 页面初始 ...

  9. java多线程 -- 同步鎖

    为了解决多线程安全问题在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile .Java 5.0 后增加了一些新的机制,但并不是一种替代内置 ...

  10. 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)

    学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...