例如去ATM領錢,此ATM是全台灣的系統,那就變成在台灣想領錢的人要等很久,如果是全世界的系統,那就等的更久,但如果只是10幾個人在用的系統,那就還ok
悲觀鎖定總共有以下11種模式:
NONE:預設值,無鎖定模式
READ:查詢時自動進行鎖定處理
UPGRADE:已廢棄-->使用PESSIMISTIC_WRITE代替
UPGRADE_NOWAIT:和UPGRADE相同,但有人鎖定就不等待返回,等同Oracle的 for update nowait
WRITE:在update、insert時自動進行鎖定處理
FORCE:已廢棄-->使用PESSIMISTIC_FORCE_INCREMENT代替
OPTIMISTIC:樂觀的假設Transaction不會出現爭用的實體
OPTIMISTIC_FORCE_INCREMENT:Transaction 立刻增加實體版本
PESSIMISTIC_READ:Implemented as PESSIMISTIC_WRITE
PESSIMISTIC_WRITE:transaction 將立即獲得一個資料庫鎖定,等同Oracle 的 for update
PESSIMISTIC_FORCE_INCREMENT:類似UPGRADE,但使用了版本記錄會強制增加版本的值
※版本在樂觀鎖定會說明
※Hibernate API的說明可參考,但還不是很清楚,可看原始碼的註解,如下:
/** * No lock required. If an object is requested with this lock * mode, a <tt>READ</tt> lock will be obtained if it is * necessary to actually read the state from the database, * rather than pull it from a cache.<br> * <br> * This is the "default" lock mode. */ public static final LockMode NONE = new LockMode(0, "NONE"); /** * A shared lock. Objects in this lock mode were read from * the database in the current transaction, rather than being * pulled from a cache. */ public static final LockMode READ = new LockMode(5, "READ"); /** * An upgrade lock. Objects loaded in this lock mode are * materialized using an SQL <tt>select ... for update</tt>. * @deprecated instead use PESSIMISTIC_WRITE */ public static final LockMode UPGRADE = new LockMode(10, "UPGRADE"); /** * Attempt to obtain an upgrade lock, using an Oracle-style * <tt>select for update nowait</tt>. The semantics of * this lock mode, once obtained, are the same as * <tt>UPGRADE</tt>. */ public static final LockMode UPGRADE_NOWAIT = new LockMode(10, "UPGRADE_NOWAIT"); /** * A <tt>WRITE</tt> 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 <tt>load()</tt> or <tt>lock()</tt> (both * of which throw exceptions if WRITE is specified). */ public static final LockMode WRITE = new LockMode(10, "WRITE"); /** * Similiar to {@link #UPGRADE} except that, for versioned entities, * it results in a forced version increment. * @deprecated instead use PESSIMISTIC_FORCE_INCREMENT */ public static final LockMode FORCE = new LockMode( 15, "FORCE" ); /** * start of javax.persistence.LockModeType equivalent modes */ /** * Optimisticly assume that transaction will not experience contention for * entities. The entity version will be verified near the transaction end. */ public static final LockMode OPTIMISTIC = new LockMode( 3, "OPTIMISTIC"); /** * Optimisticly assume that transaction will not experience contention for entities. * The entity version will be verified and incremented near the transaction end. */ public static final LockMode OPTIMISTIC_FORCE_INCREMENT = new LockMode( 4, "OPTIMISTIC_FORCE_INCREMENT"); /** * Implemented as PESSIMISTIC_WRITE. * TODO: introduce separate support for PESSIMISTIC_READ */ public static final LockMode PESSIMISTIC_READ = new LockMode( 12, "PESSIMISTIC_READ"); /** * Transaction will obtain a database lock immediately. * TODO: add PESSIMISTIC_WRITE_NOWAIT */ public static final LockMode PESSIMISTIC_WRITE = new LockMode( 13, "PESSIMISTIC_WRITE"); /** * Transaction will immediately increment the entity version. */ public static final LockMode PESSIMISTIC_FORCE_INCREMENT = new LockMode( 17, "PESSIMISTIC_FORCE_INCREMENT");
可以使用鎖定模式的有以下幾個地方(有可能還有其他地方):
Session.lock-->已廢棄
Session.refresh-->已廢棄
Session.get/load-->已廢棄
Session.buildLockRequest.lock(LockOptions)
Query.setLockMode(LockMode)
Criteria.setLockMode(LockMode)
以下是使用的情況:
Session s = HibernateUtil2.getSession(); try { Emp e1 = (Emp) s.get(Emp.class, 7369, LockMode.UPGRADE_NOWAIT); System.out.println("e1:" + e1.getEmpno()); Emp e2 = (Emp) s.get(Emp.class, 7369); LockOptions l = new LockOptions().setLockMode(LockMode.UPGRADE_NOWAIT); s.buildLockRequest(l).lock(e2); Emp e3 = (Emp) s.get(Emp.class, 7369); s.buildLockRequest(LockOptions.UPGRADE).lock(e3); Query q = s.createQuery("from Emp e where empno = 7369"); q.setLockMode("e", LockMode.UPGRADE_NOWAIT); Emp e4 = (Emp) q.uniqueResult(); System.out.println("e4:" + e4.getEname()); Criteria c = s.createCriteria(Emp.class); c.setLockMode(LockMode.PESSIMISTIC_WRITE); c.add(Restrictions.eq("empno", 7369)); Emp e5 = (Emp) c.uniqueResult(); System.out.println("e5:" + e5.getEname()); } catch (Exception e) { System.err.println("例外錯誤!"); e.printStackTrace(); } finally { if (s.isOpen()) { s.close(); } }
※e1的get或load是廢棄方法
※注意控制台的輸出有for update和for update nowait,我是用oracle的,其他資料庫有可能會不太一樣
沒有留言:
張貼留言