例如去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的,其他資料庫有可能會不太一樣
沒有留言:
張貼留言