Ошибка JPA: транзакция в данный момент активна - PullRequest
1 голос
/ 10 октября 2011

Когда я запускаю свои модульные тесты изолированно, они работают нормально, т.е. (опущены утверждения)

@Test
public void testSave()
 {
EntityManagerHelper emh = new EntityManagerHelper();
LevelDAO dao = new LevelDAO();
Level l = new Level();
l.setName("aname");
emh.beginTransaction();
dao.save(l);
emh.commit();
}

затем выполнение этого индивидуального теста без проблем

@Test
public void testUpdate()
 {
EntityManagerHelper emh = new EntityManagerHelper();
LevelDAO dao = new LevelDAO();
Level l = new Level();
l.setName("bname");
l.setLevelid(1);
emh.beginTransaction();
dao.update(l);
emh.commit();
}

Когда они выполняются одновременно в последовательности, я получаю эту ошибку - Транзакция в данный момент активна Есть ли способ разрешить запуск каждого модульного теста только после того, как транзакция из предыдущей части работы не активна? Должен ли я вместо этого смотреть на весну?

Обновление

EntityManagerHelper получает доступ к контексту персистентности следующим образом:

emf = Persistence.createEntityManagerFactory("bw_beta");        
threadLocal = new ThreadLocal<EntityManager>();

что выглядит как проблема

Таким образом, хакерский обходной путь должен был использовать определение локально, т.е..

    EntityManagerFactory factory = Persistence.createEntityManagerFactory("bw_beta");
    EntityManager entityManager = factory.createEntityManager();
    entityManager.getTransaction().begin();
    dao.save(l);
    entityManager.persist(l);
    entityManager.getTransaction().commit();

Уверен, есть лучший способ - может быть, использовать Spring?

Ответы [ 2 ]

1 голос
/ 10 октября 2011
  • Уверен, что есть лучший способ - может быть, с помощью Spring?

Да, Spring сильно его очищает и дает вам контроль над тем, что вы хотитедля выполнения в транзакции без загрязнения самого теста.

В Spring ваши тесты будут выглядеть примерно так:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:META-INF/conf/spring/application-context.xml",
                        "classpath:META-INF/conf/spring/test-datasource-spring-config.xml" })
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
public class LevelDaoTest {

    @Resource( name="levelDao" )
    LevelDao levelDao;

    @Test
    public void shouldSaveNewLevels() {

        Level l = new Level();
        l.setName("aname");
        levelDao.save(l);
        // assert
    }

    @Test
    public void shouldUpdateExistingLevels() {

        Level l = new Level(); // or I would assume, you'd read this level back from DB, or set a proper ID, so the DAO will know to update it.. But that is besides the point
        l.setName("bname");
        levelDao.update(l);
        // assert
    }
}

Посмотрите документацию Spring в разделе Testing =>Управление транзакциями для получения более подробной информации.

PS Из вашего примера:

dao.save(l);
entityManager.persist(l);

Выглядит очень странно, как обычно вы бы инкапсулировали entityManager в DAO, поэтому все, что вам нужно сделать, это dao.save(l)

0 голосов
/ 22 апреля 2016

Для тех, кто может столкнуться с этой проблемой, вот как я ее решил.Я делал несколько сохранений, и я продолжал получать эту ошибку.Вы не хотите начинать несколько транзакций без проверки, активна ли она.

if(!entityManager.getTransaction().isActive())
    entityManager.getTransaction().begin();
dao.save(l);
entityManager.persist(l);
entityManager.getTransaction().commit();

Я реализовал подход Singleton, чтобы справиться с этим.

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