Модульное тестирование Оптимистичной блокировки Hibernate (в течение весны) - PullRequest
2 голосов
/ 16 марта 2010

Я хотел бы написать модульный тест, чтобы проверить, правильно ли настроена оптимистическая блокировка (с использованием Spring и Hibernate).

Я бы хотел, чтобы тестовый класс расширил AbstractTransactionalJUnit4SpringContextTests Spring.

То, что я хочу закончить, это метод, подобный этому:


@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 отправляется обратно на сервер и объединяется с недавно загруженной сущностью, сохранение этой сущности завершится неудачей, если за это время кто-то другой обновил ее.

Ответы [ 3 ]

5 голосов
/ 20 марта 2010

Кажется, что просто невозможно перенести все поля из 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");
}

Спасибо всем за помощь в любом случае!

2 голосов
/ 16 марта 2010

Бит, который вы пропустили, это

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

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

Hibernate вернет тот же экземпляр для того же класса / идентификатора для того же сеанса.

Чтобы проверить оптимистическую блокировку, попробуйте что-то вроде:

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
1 голос
/ 17 марта 2010

С AbstractTransactionalDataSourceSpringContextTests вы бы сделали это так (код взят из этой темы ):

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() (это ключ здесь).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...