学过数据库理论的都知道,关系型数据库有ACID特征。其中I是Isolation的简写,表示数据库并发进行事务时,只有顺序,串联执行的事务才会最终反映到数据库中,即是每个成功执行的事务都是孤立分离的,它们之间不会相互影响。这个Isolation就是由数据库的锁(lock)机制来实现的。所谓的锁,也叫读锁或者写锁(分别对应于读事务及写事务的情景),锁的作用就是防止数据库在并发进行读、写事务时出现数据过时或者无效的情况。对于这些并发的用户而言,同一时间内某个用户只能更新(读事务不会影响数据状态)被加上锁的数据记录(records),加上锁后能够确保数据不能被访问,只有释放了锁后才能访问。
锁的类型有两种:悲观锁和乐观锁。悲观锁是当事务一开始就进行locking,被locked的table或者records都对外不可见,直到事务结束;乐观锁则是只有数据的更改变动向数据库提交时才进行的locking。悲观锁能够确保所有更改变动都正确提交到数据库,而乐观锁则有可能出现事务无法提交的情况(例如前一个用户已提交更改,后一个用户会提交失败,因为这时数据状态已经不是后一个用户原来读出来的那个了,已经被前一个用户更改了)。悲观锁能最大程度保证事务的隔离,但是占用数据库的开销太大(事务时间越长,开销就越大),在大并发是场景下是不可接受的。乐观锁机制在一定程度上解决了这个问题,但代价时更改不一定能够成功提交。
注意,这里的Hibernate是指4.3.5.Final版本。无论是乐观锁还是悲观锁,Hibernate都是使用数据库的锁机制实现,不会对内存的对象进行锁;
LockMode定义了Hibernate请求的锁机制,如下:
LockMode.WRITE |
当Hibernate进行updates or inserts a row时自动请求锁; |
LockMode.UPGRADE |
在数据库层面使用 |
LockMode.UPGRADE_NOWAIT |
类似UPGRAGE级别,不同的是此模式在事务不能提交时,立刻返回异常,而不是等待当前事务结束再进行等待的事务,适用于Oracle数据库 |
LockMode.UPGRADE_SKIPLOCKED |
acquired upon explicit user request using a |
LockMode.READ |
acquired automatically when Hibernate reads data under Repeatable Read or Serializable isolation level. It can be re-acquired by explicit user request. |
LockMode.NONE |
The absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call to |
具体显式编码可通过以下三种方式请求锁级别:
1.Session.load();//eg session.load(User.class, new Long(1), LockMode.UPGRADE);
2.Session.lock();//eg session.lock(user, LockMode.UPGRADE);
3.Query.setLockMode();//eg query.setLockMode("user", LockMode.UPGRADE);
在那种读操作多、写操作少的情况下,Hibernate的乐观锁能够提供一定程度的事务隔离。在遇到同样的数据先后被更改时,后更改提交的事务将会被告知冲突。
Hibernate实现乐观锁的方法有两种:1.检测版本号;2.时间戳。
UserVersionType可以实现任意类型的版本号。默认情况下用户不能认为修改version字段的值,但是可以通过更改
LockModeType.OPTIMISTIC_FORCE_INCREMENT或者LockModeType.PESSIMISTIC_FORCE_INCREMENT的值来实现手动增加版本号;column |
The name of the column holding the version number. Optional, defaults to the property name. |
name |
The name of a property of the persistent class. |
type |
The type of the version number. Optional, defaults to |
access |
Hibernate‘s strategy for accessing the property value. Optional, defaults to |
unsaved-value |
Indicates that an instance is newly instantiated and thus unsaved. This distinguishes it from detached instances that were saved or loaded in a previous session. The default value, |
generated |
Indicates that the version property value is generated by the database. Optional, defaults to |
insert |
Whether or not to include the |
当选择Date或者Calendar类型的字段作为version列时,Hibernate将会自动使用Timestamp作为version信息。例如
@Entity public class Flight implements Serializable { ... @Version public Date getLastUpdate() { ... } }
默认情况下,Hibernate读取数据库的时间作为version的时间戳,不过可以通过@org.hibernate.annotations.Source注释来控制读取的时间源:
o
rg.hibernate.annotations.SourceType.DB
;org.hibernate.annotations.SourceType.VM(来源JVM)。
此外,也可以通过配置文件方式进行配置。例如:
<timestamp
column="timestamp_column"
name="propertyName"
access="field|property|ClassName"
unsaved-value="null|undefined"
source="vm|db"
generated="never|always"
node="element-name|@attribute-name|element/@attribute|."
/>
相关的属性说明:
column |
The name of the column which holds the timestamp. Optional, defaults to the property namel |
name |
The name of a JavaBeans style property of Java type Date or Timestamp of the persistent class. |
access |
The strategy Hibernate uses to access the property value. Optional, defaults to |
unsaved-value |
A version property which indicates than instance is newly instantiated, and unsaved. This distinguishes it from detached instances that were saved or loaded in a previous session. The default value of |
source |
Whether Hibernate retrieves the timestamp from the database or the current JVM. Database-based timestamps incur an overhead because Hibernate needs to query the database each time to determine the incremental next value. However, database-derived timestamps are safer to use in a clustered environment. Not all database dialects are known to support the retrieval of the database‘s current timestamp. Others may also be unsafe for locking, because of lack of precision. |
generated |
Whether the timestamp property value is generated by the database. Optional, defaults to |
数据库乐观锁、悲观锁的初步认识,以及hibernate对它们的支持实现
原文:http://www.cnblogs.com/lauyu/p/5042154.html