带有hibernate的JUnit:这个实例在数据库中尚未作为一行存在

时间:2011-12-15 10:31:52

标签: java hibernate spring junit

我正在使用JUnit进行测试。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:com/mt/sm/application-context.xml", "classpath:com/mt/sm/security-context.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class LocationPathServiceImplTest { /* Class code here */ }

测试方法声明非常简单:

@Test
public void testRefresh() { /* Method body */}

我已在setup()中创建了保存obj并保存到db。 在@Test中我从DAO运行refresh()(refresh()方法只调用EntityManager .refresh()),但它会导致下面的错误

org.hibernate.HibernateException: this instance does not yet exist as a row in the database
javax.persistence.PersistenceException: org.hibernate.HibernateException: this instance does not yet exist as a row in the database

我不知道如何修复它。以前有人遇到过这个吗? 所有建议都将不胜感激。

我决不会将更改提交到数据库,也不会调用.flush()。为了我的理解,它们属于当前的交易范围。

3 个答案:

答案 0 :(得分:2)

如果没有更多代码我会说,你需要flush你的DAO,所以实例会被持久化。 refresh只是对象级别,而flush在数据库级别执行实际事务(因此rollback = true因此在测试后回滚)

答案 1 :(得分:1)

我不确定其他答案是否应该flush()是正确的,因为这不会对数据库提交任何内容。见Hibernate docs。刷新会话只会使当前在会话中的数据与数据库中的数据同步。因此,如果您没有在setUp()方法中调用myobject.save(),那么您的异常就有意义了。

我认为您不想在任何地方调用commit(),因为您希望在测试完成后回滚所有内容。在班级

上使用这些注释
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@Transactional

然后,您可以在setUp()方法中添加@before,但如果您的类扩展了TestCase,那么它将是相同的。 Thor84no是正确的,因为@before方法将在与@Test方法相同的事务中执行。如果您确实希望使用提交的数据为数据库设定种子,则可以使用注释为@beforeTransaction的方法。

[编辑]

根据您更新的问题,听起来您没有在您在setup()中创建的对象上调用persist()或类似内容,并且它被认为已被删除(即不会持久保存到您的数据库中)交易)。

答案 2 :(得分:0)

我还会刷新/关闭/重新打开会话以强制实际写入数据库。