2011-03-08 72 views
1

我刚刚设置了一个测试,检查我能够使用Hibernate将条目插入到我的数据库中。让我疯狂的事情是Hibernate并没有真正删除条目,虽然它报告他们已经不在了!休眠不会删除我的对象。为什么?

下面的测试运行成功,但是当我检查我的数据库之后,插入的条目仍然存在!我甚至尝试使用声明(是的,我有-ea作为虚拟机参数)来检查它。有没有人有线索为什么这些条目不被删除?

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=? 

,但是当我检查什么已被删除。

回答

4

我猜这是与交易使用不一致有关(请注意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(); 

参见:

+0

你可能是对的,因为我知道我对Hibernate正确使用的知识接近'nil'。当我明天回去工作并回报时,我会研究这是如何工作的。谢谢! – oligofren 2011-03-08 18:18:12

+0

尽管您提供的代码不够完整,但您对事务的原因是正确的。如果使用你的代码,我会得到一个异常,说当session进入session.delete()时会话被关闭。我不太清楚为什么,但我想为每个逻辑操作(可能包含多个事务)打开一个新会话更有意义。 – oligofren 2011-03-09 10:06:35

+0

还没有完成那里... 为了让一切工作,这基本上是我所做的。 在涉及查询数据库/休眠I: 的每个方法中 - 打开一个新的会话。会话会话= HibernateUtil.getSessionFactory()。openSession(); - 开始了一个新的交易 '会议。beginTransaction();' - 提交交易 'session.flush();' 'session.getTransaction()。commit();' – oligofren 2011-03-09 10:10:36

0

你可以发布你的DB模式HBM或Fluent地图?有一件事让我回想起我在我的Fluent地图中有一个ReadOnly()。它从未抛出错误,我也在日志中看到了“从blahblah = ...中删除”的错误。

+0

我会在明天检查上述交易记录是否成功后再尝试。谢谢! – oligofren 2011-03-08 18:22:34

+0

似乎这是我开始/结束创建麻烦的交易的sl way方式。不管怎么说,还是要谢谢你。 – oligofren 2011-03-09 10:11:49

1

我有同样的问题。尽管我根本没有使用交易。我用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服务器上测试过)