我想编写一个单元测试来验证是否正确设置了乐观锁定(使用Spring和Hibernate)。
我希望测试类扩展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被发送回服务器并与新加载的实体合并时,如果在此期间其他人更新了实体,那么保存该实体将会失败。
答案 0 :(得分:5)
似乎根本不是将所有字段从DTO(包括版本)转移到新加载的实体,尝试保存它,以及在DTO是DOB时修改实体时获得异常的选项在客户端修改。
原因是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");
}
无论如何,谢谢大家的帮助!
答案 1 :(得分: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
答案 2 :(得分: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()
(这是此处的关键字)。