Locking指防止关系数据库中的数据在它读取的时间和它使用的时间之间的变化的动作。
Locking分成optimistic(乐观)和pessimistic(悲观) optimistic 假定多个事务在彼此不影响的情况下完成,因此事务就能锁定数据资源的影响。 在提交之前,每个事务检查没有其他事务修改其数据,若检查出冲突的修改,该提交事务回滚。 pessimistic 假定并发事务会互相冲突,并且读后需要锁定的资源,只有应用程序已经用完数据后解锁。 Hibernate提供了在应用程序中实现这两种类型的锁定机制。 1、Optimistic 当应用程序使用长事务或跨越几个数据库事务的会话时,可以存储versioning数据,如果2个会话更新相同的实体, 最后的提交改变是一个冲突,并且不会覆盖另一个会话的工作。这种方法保证一些隔离,但具有良好伸缩性和适合于Read-Often Write-Sometimes的时候。 Hibernate提供了两种不同的机制来存储版本信息,一个专门的版本号或时间戳。 Version number Timestamp 注:一个detached对象,version or timestamp不能为null,Hibernate用一个null version or timestamp作为transient检测任何实例, 不管你指定的其他unsaved-value策略。在Hibernate中声明一个可以为null version or timestamp来避免传递reattachment问题, 如果你使用指定的标识符或组合键特别有用。 Dedicated version number @Version注解实现: public class Flight implements Serializable { ... @Column(name="OPTLOCK") public Integer getVersion() { ... } } 版本列可以是任何类型,只要你定义和实现正确的UserVersionType 注:如果版本号是由数据库生成,如trigger,使用@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)注解。 Timestamp Timestamps没有version numbers的方式可靠,但是可以使用应用程序用于其他目的。 如果@Version注解在一个Date或Calendar上时,Timestamping 是自动使用。 @Entity public class Flight implements Serializable { ... @Version public Date getLastUpdate() { ... } } Hibernate可以检索的timestamp的值从数据库或JVM,通过读取指定@org.hibernate.annotations.Source注解, 该值可以是org.hibernate.annotations.SourceType.DB或org.hibernate.annotations.SourceType.VM。 若你不指定或默认行为是使用数据库。 timestamp也可以有数据库生成,使用@org.hibernate.annotations.Generated(GenerationTime.ALWAYS)注解。 2、Pessimistic 通常,你只需要指定一个JDBC连接,让数据库隔离级别处理锁定问题。如果你需要独占pessimistic locks或 在开始一个新事务可重新获取锁,Hibernate会给你你所需要的工具。 Hibernate总是使用数据库的锁定机制,从来没有锁对象在内存中。 LockMode类定义了不同Hibernate可以获得的等级锁 LockMode.WRITE 当Hibernate更新or插入一行时自动获得 LockMode.UPGRADE 在数据库上支持的SELECT ... FOR UPDATE语法显示的用户请求 LockMode.UPGRADE_NOWAIT 在oracle中使用SELECT ... FOR UPDATE NOWAIT语法显示的用户请求 LockMode.READ Hibernate在读取数据时自动获得可重复读或可序列化的隔离级别,它可以通过显式的用户请求重新获得。 LockMode.NONE 没有锁,所有对象锁切换到该模式的一个事务。通过Session关联的对象通过调用update()或saveOrUpdate() 也开始在这个模式。 上面提到的显式的用户请求发生下列行为的结果 调用Session.load(),指定一个LockMode 调用Session.lock() 调用Query.setLockMode() 若你使用UPGRADE or UPGRADE_NOWAIT调用Session.load(),所请求的对象并不是已经加载的会话,对象加载使用SELECT ... FOR UPDATE。 如果一个使用比请求更少限制的锁已经加载的对象调用load(),Hibernate 为此对象调用lock()方法。 若指定LockMode为READ, UPGRADE, or UPGRADE_NOWAIT,Session.lock()会执行一个版本检查。 如果不支持请求的锁定模式数据库,Hibernate使用一个适当的替代模式,而不是抛出异常。这可以确保应用程序是可移植的。