Спящий режим не удаляет мои объекты. Почему?

Я только что настроил тест, который проверяет, могу ли я вставлять записи в свою базу данных с помощью Hibernate. Что меня сводит с ума, так это то, что Hibernate на самом деле не удаляет записи, хотя и сообщает, что они исчезли!

Приведенный ниже тест выполняется успешно, но когда я потом проверяю свою БД, вставленные записи все еще там! Я даже пытаюсь проверить это с помощью assert (да, у меня есть -ea как параметр vm). Кто-нибудь знает, почему записи не удаляются?

public class HibernateExportStatisticDaoIntegrationTest {
    HibernateExportStatisticDao dao;
    Transaction transaction;

    @Before
    public void setUp(){
        assert numberOfStatisticRowsInDB() == 0;
        dao = new HibernateExportStatisticDao(HibernateUtil.getSessionFactory());
    }

    @After
    public void deleteAllEntries(){
        assert numberOfStatisticRowsInDB() != 0;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        for(PersistableStatisticItem item:allStatisticItemsInDB()) {
            session.delete(item);
        }
        session.flush();
        assert numberOfStatisticRowsInDB() == 0;
    }

    @Test public void exportAllSavesEntriesToDatabase(){
        int expectedNumberOfStatistics = 20;
        dao.exportAll(StatisticItemFactory.createTestStatistics(expectedNumberOfStatistics));

        assertEquals(expectedNumberOfStatistics, numberOfStatisticRowsInDB());
    }

    private int numberOfStatisticRowsInDB() {
        return allStatisticItemsInDB().size();
    }

    @SuppressWarnings("unchecked")
    private List<PersistableStatisticItem> allStatisticItemsInDB(){
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        transaction = session.beginTransaction();
        Query q = session.createQuery("FROM PersistableStatisticItem item");
        return q.list();
    }
}

Консоль заполнена

Hibernate: delete from UPTIME_STATISTICS where logDate=? and serviceId=?

но ничего не было удалено, когда я проверял это.


person oligofren    schedule 08.03.2011    source источник


Ответы (3)


Я предполагаю, что это связано с непоследовательным использованием транзакций (обратите внимание, что beginTransaction() в allStatisticItemsInDB() вызывается несколько раз без соответствующих коммитов).

Попробуйте правильно управлять транзакциями, например, так:

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
for(PersistableStatisticItem item:
    session.createQuery("FROM PersistableStatisticItem item").list()) {
    session.delete(item);
}
session.flush();
assert session.createQuery("FROM PersistableStatisticItem item").list().size() == 0;
tx.commit();

См. также:

person axtavt    schedule 08.03.2011
comment
Вероятно, вы правы, зная, что мои знания о правильном использовании Hibernate близки к nil. Я посмотрю, как это работает, когда вернусь завтра на работу, и отчитаюсь. Спасибо! - person oligofren; 08.03.2011
comment
Вы были правы в том, что причиной были транзакции, хотя предоставленного вами кода было недостаточно. При использовании вашего кода я получу исключение, говорящее, что сеанс был закрыт, когда я доберусь до session.delete(). Я не совсем уверен, почему, но я думаю, что имеет смысл открывать новую сессию для каждой логической операции (возможно, состоящей из нескольких транзакций). - person oligofren; 09.03.2011
comment
Там было не совсем закончено ... Чтобы все заработало, это в основном то, что я сделал. В каждом методе, который включал запросы к базе данных/спящему режиму, я: - открывал новую сессию. Сеанс сеанса = HibernateUtil.getSessionFactory().openSession(); - начал новую транзакцию session.beginTransaction(); - зафиксировал транзакцию session.flush(); session.getTransaction().commit(); - person oligofren; 09.03.2011
comment
@oligofren: взгляните на docs.jboss.org/hibernate/core/3.6/reference/en-US/html/. - person axtavt; 09.03.2011

У меня точно такая же проблема. Хотя я вообще не использовал транзакцию. Я использовал namedQuery следующим образом:

Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES);
int rows = query.executeUpdate();
session.close();

Он возвращал 2 строки, но в базе данных все еще были все записи. Затем я завершаю приведенный выше код следующим образом:

Transaction transaction = session.beginTransaction();
Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES);
int rows = query.executeUpdate();
transaction.commit();
session.close();

Потом стал нормально работать. Я использовал SQL-сервер. Но я думаю, что если мы используем h2, приведенный выше код (без транзакции) также будет работать нормально. Еще одно наблюдение: для вставки и получения записей использование транзакции не обязательно, но для удаления записей нам придется использовать транзакцию. (проверено только на SQL-сервере)

person S'chn T'gai Spock    schedule 10.10.2016

Можете ли вы опубликовать свою схему БД и карты HBM или Fluent? Некоторое время назад меня привлекла одна вещь: у меня была ReadOnly() на моей карте Fluent. Это никогда не выдавало ошибку, и я тоже видел в журналах «удалить из бла, где блабла = ...».

person Al Dass    schedule 08.03.2011
comment
Я попробую это завтра, после того, как проверю, окажется ли приведенный выше след транзакции плодотворным. Спасибо! - person oligofren; 08.03.2011
comment
Кажется, это был мой небрежный способ запуска/завершения транзакций, который создал проблемы. Спасибо, в любом случае. - person oligofren; 09.03.2011