让我们先来看看Hibernate的文档时怎么说的,关于LockMode:
LockMode FORCE
Similiar to UPGRADE except that, for versioned entities, it results in a forced version increment.
LockMode NONE
No lock required.
LockMode READ
A shared lock. Objects in this lock mode were read from the database in the current transaction, rather than being pulled from a cache (注:也就是从数据库中读数据,绕过了Hibernate的Cache)
LockMode UPGRADE
An upgrade lock.(注:相当于SQL语句select xxx from xxxx for update,也就是把事务的处理交给了数据库)
LockMode UPGRADE_NOWAIT
Attempt to obtain an upgrade lock, using an Oracle-style select for update nowait.
LockMode WRITE
A WRITE lock is obtained when an object is updated or inserted.This lock mode is for internal use only and is not a valid mode for load() or lock() (both of which throw exceptions if WRITE is specified). (注:不能在load的时候用,否则抛出异常)
不过,“纸上得来终觉浅,觉知此事要躬行”,博主做了下实验来比较这些“锁”的不同。
先看代码:
package com.javaye;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.javaye.models.Article;
public class Main {
private static void insert(){
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Article art = new Article();
art.setTitle("AAA");
art.setVisitAmount(0);
session.saveOrUpdate(art);
tx.commit();
}
private static void update(){
Session session = HibernateSessionFactory.getSession();
System.out.println("session:"+session.hashCode());
Transaction tx = session.beginTransaction();
Article art = (Article) session.load(Article.class, 1,LockMode.UPGRADE);
System.out.println(" loaded");
art.setVisitAmount(art.getVisitAmount()+1);
session.save(art);
tx.commit();
session.evict(art);
}
private static void work(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+(i+1)+"times.");
update();
}
}
public static void main(String[] args) throws Exception{
Thread t1 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
Thread t2 = new Thread(
new Runnable(){
public void run(){
work();
}
}
);
t1.setName("Thread1");
t2.setName("Thread2");
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
这是一个多线程程序,每个线程都会从数据库中取出visit_amount,然后加一,再存回数据库,每个线程重复10遍。
请注意蓝色的部分,我们在这里设一个断点,那么用Eclipse调试的时候,到达这个断点的线程就会停下来,由于它的事务还没有commit(),LockMode.UPGRADE的锁就还没有释放,那么另外一个线程中事务就会在load的时候因为不能获得锁而阻塞,那么理论上我们只会看到只有一句“ loaded ”输出。 实验结果证明了我的猜想,LockMode.UPGRADE的情况下,如果一个事务获得了锁,即使另外的事务想读取数据也是不行的,必须等待锁的释放。
那么,改写数据可以吗?笔者又做了一个实验,打开MySQL Query Browser,直接生改数据库,把visit_amount字段的值硬生生改过来,结果发现提交的时候就阻塞了,MySQL的海豚标志一个劲的游泳,这说明,LockMode.UPGRADE级别的锁不是由Hibernate控制的,而是由数据库控制的。
再试一试LockeMode.Read,断点还是设在原来的位置,发现有两次“ loaded”输出,证明两个事务可以同时读取这条数据,那么这个锁有什么作用呢?根据我实验的结果,似乎只是为了绕过cache,从数据库直接读取。为了证明我的猜想,我直接通过MySQL Query Browser更改了visit_amount,调试发现,Hibernate是从数据库中读取的新值,而不是cache中的老值。
最后在补充一点,LockMode.UPGRADE加锁是有超时时间的,如果加锁后超过一定的时间不commit,Hibernate会抛出异常。
原文地址 http://www.javaye.com/blog/post/hibernate_lockmode.html
分享到:
相关推荐
Hibernate 3.2 是一个流行的Java对象关系映射(ORM)框架,它允许开发者使用面向对象的编程模型来操作数据库,而无需直接编写SQL语句。这个版本的Hibernate引入了许多改进和新特性,旨在提高性能和开发效率。CGlib...
Hibernate提供了LockMode类型的锁,如LockMode.READ、LockMode.WRITE和LockMode.UPGRADE,分别对应不同的锁定级别。 此外,Hibernate还支持读写分离和第二级缓存来优化并发性能。读写分离将读操作和写操作分散到...
在Hibernate中,悲观锁可以通过`LockMode`进行设置,如`LockMode.WRITE`、`LockMode.UPGRADE`等。例如,使用`session.get()`或`session.createQuery().setLockMode()`方法可以在查询时加锁。`LockMode.UPGRADE`会...
- `LockMode.WRITE`:Hibernate在插入或更新记录时自动获取。 - `LockMode.READ`:Hibernate在读取记录时自动获取。 - `LockMode.UPGRADE`:利用数据库的`FOR UPDATE`子句加锁。 - `LockMode.UPGRADE_NOWAIT`:...
2. **LockMode**: Hibernate提供了LockMode类,可以通过Session的`lock()`或`update()`方法,指定LockMode.PESSIMISTIC_WRITE或LockMode.PESSIMISTIC_READ来获取悲观锁。 **乐观锁**(Optimistic Lock)则相对乐观...
在悲观锁中,Hibernate提供了多种锁模式,如`LockMode.NONE`、`LockMode.WRITE`、`LockMode.READ`等,这些主要由内部使用。而`LockMode.UPGRADE`和`LockMode.UPGRADE_NOWAIT`(Oracle特有的)则是我们在应用程序中...
Hibernate支持的悲观锁模式有`LockMode.UPGRADE`(对应SQL的`for update`)和`LockMode.UPGRADE_NOWAIT`(Oracle特有的,用于立即返回等待超时的结果)。 **乐观锁(Optimistic Locking)** 乐观锁则相对乐观,它...
8. 锁章节,讨论了Hibernate提供的乐观锁和悲观锁的实现,包括使用版本号、时间戳、LockMode类等方法来控制并发访问。 9. Fetching(抓取)章节,说明了如何配置和应用不同的抓取策略来优化数据库访问和提升性能。...
Hibernate还支持LockMode,包括READ、WRITE、UPGRADE和OPTIMISTIC等,以适应不同级别的并发控制需求。 三、缓存管理 缓存技术可以显著提升应用性能,减少数据库访问。Hibernate的缓存分为一级缓存和二级缓存。一级...
- `load(Class<T> theClass, Serializable id, LockMode lockMode)`:根据类类型、主键和锁定模式加载对象。 - `load(Object object, Serializable id)`:根据对象和主键加载对象。 - **`createQuery` 方法**:...
### Hibernate 开发者指南知识点详解 #### 一、前言 Hibernate是一款开源的对象关系映射(Object Relational Mapping,简称ORM)框架,它为Java应用提供了对关系型数据库的高效持久化支持。Hibernate的主要特点...
锁章节讲解了乐观锁和悲观锁的使用和管理,包括乐观锁的版本号和时间戳机制,悲观锁的使用以及LockMode类的介绍。 9. Fetching(抓取): 抓取章节介绍了抓取策略,包括不抓取、通过查询动态抓取以及通过配置文件...
在 Hibernate 中,悲观锁的实现方式有多种,例如使用 `LockMode.UPGRADE` 加锁方式,或者使用 `for update` 语句来锁定数据。在查询开始之前加锁,才会真正通过数据库的锁机制加锁处理。 二、乐观锁(Optimistic ...
### Hibernate的乐观锁与悲观锁 #### 一、引言 在并发环境下,尤其是在金融、电商等业务场景中,确保数据的一致性和完整性至关重要。**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制...
为了保证多线程环境下的数据一致性,Hibernate提供了缓存同步机制,如LockMode和Locking Strategy。通过这些机制,可以在并发环境下控制对缓存的访问,防止脏读、不可重复读和幻读等问题。 **七、最佳实践** 1. **...
在Hibernate框架中,悲观锁通过`LockMode.PESSIMISTIC_READ`和`LockMode.PESSIMISTIC_WRITE`来实现。`PESSIMISTIC_READ`通常用于读取数据时避免其他事务更新,而`PESSIMISTIC_WRITE`则更严格,不仅阻止更新,也阻止...
对于 Criteria 还可以设置 FlushModel(冲刷 Session 的方式)和 LockMode(数据库锁模式)。 Criterion 是 Criteria 的查询条件。Criteria 提供了 add(Criterion criterion) 方法来添加查询条件。Criterion 接口的...
Account a = (Account) session.load(Account.class, 1, LockMode.UPGRADE); int balance = a.getBalance(); // do some calculation balance = balance - 10; a.setBalance(balance); session.getTransaction...
Criteria 还提供了其他一些有用的用法,如设置 FetchMode(联合查询抓取的模式)、设置排序方式、设置 FlushModel(冲刷 Session 的方式)和 LockMode(数据库锁模式)。通过这些设置,可以满足复杂的查询需求。 ...