文档章节

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的悲观锁和乐观锁机制

有些业务逻辑在执行过程中要求对数据进行排他性的访问,于是需要通过一些机制保证在此过程中数据被锁住不会被外界修改,这就是所谓的锁机制。 Hibernate支持悲观锁和乐观锁两种锁机制。悲观锁...

唐怀瑟
07/25
0
0
Hibernate的乐观锁与悲观锁

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

four
2011/03/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

好用的vue组件

http://elickzhao.github.io/2017/08/vue%E4%B8%80%E4%BA%9B%E7%89%B9%E5%88%AB%E6%9C%89%E7%94%A8%E7%9A%84%E6%8F%92%E4%BB%B6/...

Littlebox
23分钟前
2
0
linux 源码安装mysql8

1.安装依赖 yum -y install wget cmake gcc gcc-c++ ncurses ncurses-devel libaio-devel openssl openssl-devel   2.下载源码包 wget https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-......

苏牧影子
23分钟前
1
0
BeanFactory和FactoryBean

BeanFactory BeanFactory是ioc容器的顶层接口,里面定义了一些容器基本的功能 类似ConfigurableBeanFatory和ApplicationContext就是比较高级的容器,除了基本的方法之外,还实现了很多高级的...

sendo
25分钟前
1
0
Java并发(9)- 从同步容器到并发容器

引言 容器是Java基础类库中使用频率最高的一部分,Java集合包中提供了大量的容器类来帮组我们简化开发,我前面的文章中对Java集合包中的关键容器进行过一个系列的分析,但这些集合类都是非线...

Ala6
29分钟前
2
0
Java定时器Timer学习之一

种类: 接通延时型定时器:接通延时型定时器是各种PLC(可编程控制器)中最常见最基本的定时器,这种定时器在Siemens的PLC中,成为SD型定时器 断开延时型定时器:这种定时器是当输入条件00000为ON时...

王怀楼
31分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部