day36 10-Hibernate中的事务:解决丢失更新

演示hibernate如何产生丢失更新的


 丢失更新是怎么玩的?首先两个事务先都把它查出来。

A事务里面去修改的数据没了,被B事务覆盖掉了。这是被B事务提交覆盖,B事务回滚也能覆盖。这就是丢失更新的效果。


悲观锁使用了数据库的锁机制,

这就是悲观锁的解决方案,但是这种方式并不是特别的好。因为这条记录被锁定了,其他人都不能操作这条记录了。必须等排它锁被释放完其他人才能操作,这是悲观锁来解决。


 乐观锁来解决。

这是关于session的一些本地操作,一会我们来说它。

 


乐观锁是怎么做的?相当于在我们这里加了一个版本号。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping package="cn.itcast.vo"><!-- 如果这里配置了包名下面可以不用写 -->
<!--
<hibernate-mapping>
-->
<!--  
    <class name="cn.itcast.hibernate3.demo2.Customer" table="customer">
    -->
    <!-- 
    <class name="cn.itcast.vo.Customer" table="customer">
        -->
            <class name="Customer" batch-size="2" table="customer">
        <!-- 配置唯一标识 -->
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <!-- version标签是版本号 -->
        <version name="version"></version>
        <!-- 配置普通属性 -->
        <property name="cname" column="cname" length="30"/>
        <property name="age" column="age" length="30"/>
        
        <!-- 建立映射 -->
        <!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. -->
        <!-- 这里把级联去掉  要最简短的配置 
        <set name="orders" cascade="save-update" inverse="true">
-->
<set name="orders" cascade="save-update" batch-size="2">
            <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. -->
            <key column="cno"></key>
            <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 -->
            <!--  
            <one-to-many class="cn.itcast.hibernate3.demo2.Order"/>
            -->
            <one-to-many class="cn.itcast.vo.Order"/>
        </set>
    </class>
    <!-- 命名查询的方式 -->
    <query name="findAll">
    from Customer 
    </query>
    <!--  这里要写sql语句
    <sql-query>
    
    </sql-query>
    -->
</hibernate-mapping>
package cn.itcast.test;

import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.utils.HibernateUtils;
import cn.itcast.vo.Customer;

/**
 * 
 * Hibernate的事务管理:
 * @author zhongzh
 *
 */
public class HibernateDemo3 {
    @Test
    /*
     * 使用乐观锁解决丢失更新  也需要两个事务同时操作这条记录。
     */
      public void demo6(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        
          Customer customer = (Customer) session.get(Customer.class, 3);
          customer.setAge(26);
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用乐观锁解决丢失更新
     */
      public void demo5(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        
          Customer customer =  (Customer) session.get(Customer.class, 3);
          customer.setCname("沈明贞");
          
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用悲观锁解决丢失更新  底层执行的是同一个,只不过事务不一样而已
     */
      public void demo4(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
        // 使用悲观锁(排它锁)
            @SuppressWarnings("deprecation")
            Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE);
            customer.setAge(32);
          tx.commit();
          session.close();
      }
    @Test
    /*
     * 使用悲观锁解决丢失更新
     */
    public void demo3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // 使用悲观锁(排它锁)
        @SuppressWarnings("deprecation")
        Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE);
        customer.setCname("沈明贞");
        tx.commit();
        session.close();
    }
    
      @Test
      /*
       * 
       * 丢失更新的产生
       * 
       */
      public void demo2(){
          Session session = HibernateUtils.openSession();
          Transaction tx = session.beginTransaction();
          Customer customer =   (Customer) session.get(Customer.class, 3);
         //再有一个事务去更新customer的年龄
          customer.setAge(30);//持久态对象不用手动调update都可以完成更新
          
          //System.out.println(customer);
          tx.commit();
          session.close();
      }
  @Test
  /*
   * 
   * 丢失更新的产生
   * 
   */
  public void demo1(){
      Session session = HibernateUtils.openSession();
      Transaction tx = session.beginTransaction();
      Customer customer =   (Customer) session.get(Customer.class, 3);
      //假设就有一个事务在更新这个customer的名称
      customer.setCname("沈明贞");
      
      //System.out.println(customer);
      tx.commit();
      session.close();
  }
}
原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/6702654.html