Принудительно перезагрузить JPA EntityManager в интеграционном тесте

В интеграционном тесте с поддержкой Spring мне нужно заставить EntityManager повторно читать из базы данных.

@Test
@DataSet("/xml/dbunit/truncate-tables.xml")
public void createTerminalFromQuery() {

    // there should be zero terminals in the empty database
    Assert.assertEquals(0, terminalService.countTerminals());

    // makes remote REST call updating database outside the application's EntityManager
    HttpEntity<QueryResponse> result = simulateRequest("query");

    // attempts to force re-read of updated database (unsuccessfully)
    entityManagerService.getEntityManager().flush();

    // there should be exactly one Terminal in the database
    Assert.assertTrue(terminalService.existsTerminalBySerialNumber(EXISTING_TERMINAL_SERIAL_NUMBER));

}

Проверено, что Терминал создан и существует в базе данных. Несмотря на это, второе утверждение неверно. Когда первое утверждение закомментировано, второе в порядке.

Тестовая среда — это Unitils/DBUnit, и внедрение EntityManager через @PersistenceContext затруднено, так как требуемый пакет unitils-orm зависит от Spring 2.5 и JPA 1.0, что приводит к другим проблемам.

Вместо этого я создал EntityManagerService и убедился, что он действительно использует тот же EntityManager, что и TerminalService.

Я пробовал EntityManager.clear() и flush() и вытеснял кэш из EntityManagerFactory, но, похоже, ничего не дало никакого эффекта.

Какие-либо предложения?


person morsor    schedule 22.07.2011    source источник


Ответы (1)


Непонятно, как вы управляете транзакциями. Поскольку clear() не помогает, возможно, обе проверки выполняются внутри одной и той же транзакции, которая не видит результата транзакции, зафиксированной службой REST.

Попробуйте выполнить проверки в разных транзакциях.

person axtavt    schedule 22.07.2011
comment
Транзакции в вызываемых службах обрабатываются Spring, но мое понимание транзакций очень простое. Как обеспечить выполнение двух утверждений в разных транзакциях? Я попытался обернуть каждое утверждение в его собственный частный метод с помощью @Transactional Propagation.REQUIRES_NEW (в отчаянной попытке принудительно выполнить фиксацию/перезагрузку/обновление), но это также не дало никакого эффекта. - person morsor; 22.07.2011
comment
@morsor: я не совсем понимаю, как ваш EntityManagerService взаимодействует с транзакциями, управляемыми Spring. Если он создает EntityManagers вручную, они, вероятно, не имеют ничего общего с управляемыми транзакциями Spring, поэтому вам следует управлять транзакциями вручную, вызывая методы EntityManagers. - person axtavt; 22.07.2011
comment
EntityManagerService связывает тот же EntityManager, что и Terminalservice, используя @PersistenceContext. Обе службы управляются компонентами Spring. - person morsor; 22.07.2011
comment
Вы говорите, что я должен программно обрабатывать транзакции в интеграционном тесте? - person morsor; 22.07.2011
comment
Оказалось, что транзакции в интеграционном тесте неявно обрабатывались тестовой средой Unitils, пока я не аннотировал методы с помощью @Transactional(value = TransactionMode.DISABLED). Это решило мою насущную проблему и вызвало пару новых :-) Спасибо, что указали мне правильное направление. - person morsor; 25.07.2011