文档章节

hibernate---->悲观锁和乐观锁

小强斋太
 小强斋太
发布于 2016/11/09 20:07
字数 676
阅读 1
收藏 0

一、悲观锁

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

悲观锁的实现:

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

  • 调用 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) 


 

 

本文转载自:http://www.cnblogs.com/xqzt/archive/2012/09/06/5637187.html

共有 人打赏支持
小强斋太
粉丝 0
博文 181
码字总数 0
作品 0
广州
Java程序员从笨鸟到菜鸟之(七十六)细谈Hibernate(十八)悲观锁和乐观锁解决hibernate并发

锁( locking ),这个概念在我们学习多线程的时候曾经接触过,其实这里的锁和多线程里面处理并发的锁是一个道理,都是暴力的把资源归为自己所有。这里我们用到锁的目的就是通过一些机制来保...

长平狐
2012/11/12
94
0
Hibernate数据库的并发

7、数据库的并发:当多个用户同时修改数据库时的处理。这一部分只是在一些特殊情况才考虑。 7.1、并发修改可能出现的问题 当两个线程同时修改一个对象时,后操作的对象会将前一个操作对象所更...

pmos
2016/10/25
43
0
hibernate 乐观锁与悲观锁使用

总结一句话概述 当多个事务同时使用相同数据时会导致并发问题,此时只能用锁来限制。 悲观锁:直接锁住数据库,一个用完,下个才能用,开销大。 乐观锁:数据库中增大version字段,每次提交时...

长平狐
2013/01/06
437
0
Hibernate的乐观锁与悲观锁

转帖:谢谢分享 锁( locking ) 业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在金融系统的日终结算处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行...

four
2011/03/24
0
0
Hibernate(五)——面向对象查询语言和锁

Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了。但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hiber...

凡尘里的一根葱
2015/11/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JS:异步 - 面试惨案

为什么会写这篇文章,很明显不符合我的性格的东西,原因是前段时间参与了一个面试,对于很多程序员来说,面试时候多么的鸦雀无声,事后心里就有多么的千军万马。去掉最开始毕业干了一年的Jav...

xmqywx
今天
0
0
Win10 64位系统,PHP 扩展 curl插件

执行:1. 拷贝php安装目录下,libeay32.dll、ssleay32.dll 、 libssh2.dll 到 C:\windows\system32 目录。2. 拷贝php/ext目录下, php_curl.dll 到 C:\windows\system32 目录; 3. p...

放飞E梦想O
今天
0
0
谈谈神秘的ES6——(五)解构赋值【对象篇】

上一节课我们了解了有关数组的解构赋值相关内容,这节课,我们接着,来讲讲对象的解构赋值。 解构不仅可以用于数组,还可以用于对象。 let { foo, bar } = { foo: "aaa", bar: "bbb" };fo...

JandenMa
今天
1
0
OSChina 周一乱弹 —— 有人要给本汪介绍妹子啦

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享水木年华的单曲《中学时代》@小小编辑 手机党少年们想听歌,请使劲儿戳(这里) @须臾时光:夏天还在做最后的挣扎,但是晚上...

小小编辑
今天
21
5
centos7安装redis及开机启动

配置编译环境: sudo yum install gcc-c++ 下载源码: wget http://download.redis.io/releases/redis-3.2.8.tar.gz 解压源码: tar -zxvf redis-3.2.8.tar.gz 进入到解压目录: cd redis-3......

hotsmile
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部