save方法 - 在发生异常后不刷新会话

时间:2011-03-14 12:53:46

标签: hibernate playframework

public class SoftwareTest extends UnitTest {

    @Before
    public void setup() {
        Fixtures.deleteAll(); // will fail if comment that. why?????
    }

    @Test
    public void createSoftwareWithNullAuthor()  {

       // when author is null

       Author nullAuthor = null;

       Software software = new Software("software1", "description1", nullAuthor);
       try {
         software.save();
         fail("author should not be null");
       } catch (PersistenceException ex) {
       }

    }


    @Test
    public void createSoftwareWithOkAuthor()  {
       // when author is ok
       Author okAuthor = new Author("author1", "email1").save(); // ERROR HERE!

       Software software2 = new Software("software2", "description2", okAuthor);
       Software savedSoftware = software2.save();
       assertNotNull(savedSoftware);
       assertEquals(savedSoftware, software2); 

       assertNotNull(savedSoftware.author);
       assertEquals(okAuthor, savedSoftware.author);
    }
}

在使用Fixtures.deleteAll()取消注释该行时,我们将在第二种方法中获得例外 - createSoftwareWithOkAuthor()当作者save()时。 为什么会这样?

org.hibernate.AssertionFailure: null id in models.Software entry (don't flush the Session after an exception occurs)
  at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:82)
  at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190)
  at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147)
  at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:240)
  at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
  at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
  at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)

3 个答案:

答案 0 :(得分:11)

从错误:

  {p} org.hibernate.AssertionFailurenull id条目中models.Software(发生异常后不要刷新Session

我们可以看到会话异常发生在之前。引发此org.hibernate.AssertionFailure的点不是错误发生的点。

那就是:有些东西正在压制原来的例外。

所以寻找其他可能的错误点。 save()saveOrUpdate()可能会尝试保留具有null字段的实体,其中表格中的列为NOT NULL

在我的情况下,真实异常发生在try/catch {}区块内,catch代表该异常(没有重新抛出或警告我)。

答案 1 :(得分:8)

问题似乎是Hibernate引发异常(因此当前事务失效)但是你试图在该会话中继续进行更多操作。

执行此操作的正确方法是将您正在使用的测试拆分为2,一部分用于测试空作者,另一部分用有效作者进行测试。

在生产代码(比如控制器)上,您需要重新启动操作(关闭事务,重新启动进程)才能继续。但是考虑到play管理事务的方式,正常的行为是在错误之后你将返回错误消息给用户。

答案 2 :(得分:1)

也许有人会重复我的错误:

我也遇到过这个问题。在我的情况下,问题已经发生,因为我设置了column类型integer,并尝试写入long值。更改column类型后,它就开始工作了。