2010-03-16 85 views
2

我想編寫一個單元測試來驗證樂觀鎖定是否正確設置(使用Spring和Hibernate)。單元測試Hibernate的樂觀鎖定(在Spring中)

我想讓測試類擴展Spring的AbstractTransactionalJUnit4SpringContextTests

我想直到結束是這樣的方法:


@Test (expected = StaleObjectStateException.class) 
public void testOptimisticLocking() { 
    A a = getCurrentSession().load(A.class, 1); 
    a.setVersion(a.getVersion()-1); 
    getCurrentSession().saveOrUpdate(a); 
    getCurrentSession().flush();   
    fail("Optimistic locking does not work"); 
} 

此測試失敗。你推薦什麼作爲最佳實踐?

我試圖這樣做的原因是我想將version轉移到客戶端(使用DTO)。我想證明,當DTO被髮送回服務器並與新加載的實體合併時,如果在此期間其他人已經更新,則保存該實體將失敗。

回答

5

看來,它不是一個選項來將所有字段從DTO(包括版本)轉移到新加載的實體,嘗試保存它,並且在DTO的實體被修改的情況下獲取異常正在客戶端進行修改。

原因是因爲你在同一個會話中工作,Hibernate根本不在意你對版本字段做了什麼。版本字段的值由會話記住。

的一個簡單證明:


@Test (expected = StaleObjectStateException.class) 
public void testOptimisticLocking() { 
    A a = getCurrentSession().load(A.class, 1); 
    getCurrentSession().evict(a); //comment this out and the test fails 
    a.setVersion(a.getVersion()-1); 
    getCurrentSession().saveOrUpdate(a); 
    getCurrentSession().flush();   
    fail("Optimistic locking does not work"); 
} 

謝謝大家的幫助呢!

+0

是的這個工程!謝謝 – 2015-01-09 14:59:25

2

這裏你缺少的位

A a1 = getCurrentSession().load(A.class, 1); 
A a2 = getCurrentSession().load(A.class, 1);  

System.out.println("the following is true!! " + a1 == a2) ; 

Hibernate會返回同一個實例同一類/ ID同一會話。

爲了測試樂觀鎖定嘗試像一些事情:

A a1 = getCurrentSession().load(A.class, 1); 

// update the version number in the db using some sql. 
runSql("update A set version = version + 1 where id = 1"); 

// change object 
a1.setField1("Thing"); 

getCurrentSession().flush(); // bang should get exception here 
+0

感謝您的答案(+1),這將測試樂觀鎖定。我會嘗試更新這個問題,但要充分反映我試圖達到的目標。 – 2010-03-16 16:42:18

+0

沒有問題...稍後有一點我不是工作...已經花了太多時間在今天:) – 2010-03-16 17:48:34

1

隨着AbstractTransactionalDataSourceSpringContextTests,你會做這樣的(從this thread採取代碼):

public void testStatelessDetectedOnObjectWithOptimisticLocking() { 
    long id = 1l; 
    CoffeeMachine cm1 = (CoffeeMachine) hibernateTemplate.get(CoffeeMachine.class, id); 
    Session firstSession = hibernateTemplate.getSessionFactory().getCurrentSession(); 

    endTransaction(); 

    // Change outside session 
    cm1.setManufacturerName("And now for something completely different"); 

    startNewTransaction(); 
    Session secondSession = hibernateTemplate.getSessionFactory().getCurrentSe ssion(); 
    assertNotSame(firstSession, secondSession); 

    CoffeeMachine cm2 = (CoffeeMachine) hibernateTemplate.get(CoffeeMachine.class, id); 
    cm2.setManufacturerName("Ha ha! Changed by someone else first. Beat you!"); 

    hibernateTemplate.flush(); 

    try { 
     hibernateTemplate.merge(cm1); 
     fail("Stateless should be detected"); 
    } 
    catch (OptimisticLockingFailureException ex) { 
    // OK 
    } 
} 

的使用注意事項startNewTransaction()(這裏是關鍵)。

+0

謝謝,我已經看到這個,但AbstractTransactionalJUnit4SpringContextTests沒有交易方法... – 2010-03-17 09:42:17