3

I'd like to write a unit test to verify that optimistic locking is properly set up (using Spring and Hibernate).

I'd like to have the test class extend Spring's AbstractTransactionalJUnit4SpringContextTests.

What I want to end up with is a method like this:

 @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"); } 

This test fails. What do you recommend as a best practice?

The reason I am trying to do this is that I want to transfer the version to the client (using a DTO). I want to prove that when the DTO is sent back to the server and merged with a freshly loaded entity, saving that entity will fail if it's been updated by somebody else in the meantime.

0

3 Answers 3

7

It seems that it simply isn't an option to transfer all the fields from a DTO (including version) to a freshly loaded entity, try to save it, and get an exception in case the entity was modified while the DTO was being modified on the client.

The reason for that is that Hibernate simply doesn't care what you do to the version field, given that you're working in the same session. The value of the version field is remembered by the session.

A simple proof of that:

 @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"); } 

Thanks everyone for help anyway!

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah it's really dumb. Copying a program that triggers the optimistic locks every time into a test just doesn't work. It doesn't throw the exception and just persists instead.
2

The bit your missing here is

A a1 = getCurrentSession().load(A.class, 1); A a2 = getCurrentSession().load(A.class, 1); System.out.println("the following is true!! " + a1 == a2) ; 

Hibernate will return the same instance for the same class/id for the same session.

In order to test the optimistic locking try some thing like:

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 Comments

Thanks for the answer (+1), this will test optimistic locking. I'm gonna try to update the question though to fully reflect what I'm trying to achieve.
no problems... will have a bit later once I'm not a work... already spent too much time on SO today :)
1

With an AbstractTransactionalDataSourceSpringContextTests, you would do it like this (code taken from 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 } } 

Note the use of startNewTransaction() (that's the key here).

1 Comment

Thanks, I've seen this but AbstractTransactionalJUnit4SpringContextTests does not have the transaction methods...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.