• hibernate>悲观锁和乐观锁


    一、悲观锁

    悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改

    悲观锁的实现:

    显式的用户指定"可以通过以下几种方式之一来表示:

    • 调用 Session.load()的时候指定锁定模式(LockMode)

    • 调用Session.lock()

    • 调用Query.setLockMode()

    package com.wsz.test;
    
    import junit.framework.TestCase;
    
    import org.hibernate.LockMode;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.wsz.entity.HibernateUtils;
    import com.wsz.entity.Products;
    
    public class Test extends TestCase {
    
    	public void testSave() {
    		Session session = null;
    		Transaction tx = null;
    		Products products = null;
    		try {
    			session = HibernateUtils.getSession();
    			tx = session.beginTransaction();
                products=new Products();
                products.setName("脑白金");
                products.setTotalnumber(1000);
                session.save(products);
    			tx.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    			tx.rollback();
    		} finally {
    			HibernateUtils.closeSession(session);
    		}
    
    	}
    
    	public void test1() {
    
    		Products products = new Products();
    		Session session = HibernateUtils.getSession();
    		session.beginTransaction();
    		//悲观锁的实现
    		products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
    		System.out.print(products.getName());
    		System.out.println(products.getTotalnumber());
    		products.setTotalnumber(products.getTotalnumber()-200);
    		session.getTransaction().commit();
    
    	}
    	
    	
    	public void test2() {
    
    		Products products = new Products();
    		Session session = HibernateUtils.getSession();
    		session.beginTransaction();
    		products = (Products) session.load(products.getClass(), 1,LockMode.UPGRADE);
    		System.out.print(products.getName());
    		System.out.println(products.getTotalnumber());
    		products.setTotalnumber(products.getTotalnumber()-200);
    		session.getTransaction().commit();
    
    	}
    
    }
    

    使用悲观锁,lazy属性失效,立即发出sql。

    二、乐观锁

    大多数基于数据版本记录机制(version)实现,一般是在数据库表中加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据表中的版本号,则认为数据是过期的,否则给予更新。

    Products.hbm.xml

    <hibernate-mapping>
    	<class name="com.wsz.entity.Products" table="t_products" optimistic-lock="version">
    		<id name="id">
    			<generator class="native" />
    		</id>
    		<version name="version"/>
    		<property name="name" />
    		<property name="totalnumber" />
    	</class>
    </hibernate-mapping>

    数据库表多了一个version字段

    开始version=0

    如果更新后 version=1,由数据库自动更新。

    Products.java

    package com.wsz.entity;
    
    
    public class Products {
    	private int id;
    	private String name;
    	private int  totalnumber;
    	private int version;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getTotalnumber() {
    		return totalnumber;
    	}
    	public void setTotalnumber(int totalnumber) {
    		this.totalnumber = totalnumber;
    	}
    	public int getVersion() {
    		return version;
    	}
    	public void setVersion(int version) {
    		this.version = version;
    	}
    	
    
    
    
    }
    

    Test.java

    package com.wsz.test;
    
    import junit.framework.TestCase;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.wsz.entity.HibernateUtils;
    import com.wsz.entity.Products;
    
    public class Test extends TestCase {
    
    	public void testSave() {
    		Session session = null;
    		Transaction tx = null;
    		Products products = null;
    		try {
    			session = HibernateUtils.getSession();
    			tx = session.beginTransaction();
                products=new Products();
                products.setName("naobaijin");
                products.setTotalnumber(1000);
                session.save(products);
    			tx.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    			tx.rollback();
    		} finally {
    			HibernateUtils.closeSession(session);
    		}
    
    	}
    
    	public void test1() {
    
    		Products products = new Products();
    		Session session = HibernateUtils.getSession();
    		session.beginTransaction();
    		//悲观锁的实现
    		products = (Products) session.load(products.getClass(), 1);
    		System.out.print(products.getName());
    		System.out.println(products.getTotalnumber());
    		products.setTotalnumber(products.getTotalnumber()-200);
    		session.getTransaction().commit();
    
    	}
    	
    	
    	public void test2() {
    
    		Products products = new Products();
    		Session session = HibernateUtils.getSession();
    		session.beginTransaction();
    		products = (Products) session.load(products.getClass(), 1);
    		System.out.print(products.getName());
    		System.out.println(products.getTotalnumber());
    		products.setTotalnumber(products.getTotalnumber()-200);
    		session.getTransaction().commit();
    
    	}
    
    }
    

    使用悲观锁,lazy不会失效,不会立即发出sql

    更新时发出的sql语句Hibernate: update t_products set version=?, name=?, totalnumber=? where id=? and version=?,

    如果test1更新了,在commit设置断点,没有提交,test2更新了。此时test1往下运行,当前的version 小于数据库的version ,会生成如下的异常。

    10:48:59,260 ERROR AbstractFlushingEventListener:301 - Could not synchronize database state with session
    org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.wsz.entity.Products#1]
     at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1699) 


     

  • 相关阅读:
    分解让复杂问题简单化:字符串的排列
    分解让复杂问题简单化:二叉搜索树与双向链表
    分解让复杂问题简单化:复杂链表的复制
    举例让抽象问题具体化:二叉树中和为某一值的路径
    举例让抽象问题具体化:二叉搜索树的后序遍历序列
    Java Collection Framework
    Spring Boot 项目部署到本地Tomcat,出现访问路径问题
    happens-before规则
    NoClassDefFoundError
    《Java编程思想》笔记 第十六章 数组
  • 原文地址:https://www.cnblogs.com/xqzt/p/5637187.html
Copyright © 2020-2023  润新知