保存方法 - 发生异常后不刷新会话

Posted

技术标签:

【中文标题】保存方法 - 发生异常后不刷新会话【英文标题】:save method - doesn't flush the Session after an exception occurs 【发布时间】:2011-07-15 00:06:55 【问题描述】:
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() 行时,我们将在第二种方法中得到 en 异常 - 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)

【问题讨论】:

我在这里详细介绍了导致此类错误的流程:***.com/a/53062970/2087640 【参考方案1】:

来自错误:

org.hibernate.AssertionFailure: null id in models.Software 条目(发生异常后不要刷新Session

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

即:某些东西正在抑制原始异常。

所以寻找其他可能的错误点。 save()saveOrUpdate() 可能正在尝试使用 null 字段持久化一个实体,其中,在表中,该列是 NOT NULL

在我的例子中,真正的异常发生在 try/catch 块内,catch 抑制了异常(没有重新抛出或警告我)。

【讨论】:

【参考方案2】:

问题似乎是 Hibernate 引发了异常(因此当前事务无效),但随后您尝试在该会话中继续执行更多操作。

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

在生产代码(假设是控制器)上,您需要重新启动操作(关闭事务,重新启动流程)才能继续。但是考虑到 play 管理事务的方式,正常的行为是在错误发生后您只会向用户返回一条错误消息。

【讨论】:

是的。这行得通,但我也试过了。但是还有另一个问题:在 @Before setup() 方法中,我有 Fixtures.deleteAll();如果我在此处评论此行,那么我将在第二种(拆分)方法中遇到相同的错误。这里:作者 okAuthor = new Author("author1", "email1").save(); 我们怎样才能停止会话不失效?【参考方案3】:

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

我也遇到过这个问题。就我而言,问题发生是因为我设置了column 类型integer,并尝试写入long 值。更改column 类型后,它开始工作。

【讨论】:

就我而言,我没有放置 ManyToOne 和 JoinColumn 注释

以上是关于保存方法 - 发生异常后不刷新会话的主要内容,如果未能解决你的问题,请参考以下文章

org.hibernate.AssertionFailure: [...] 条目中的空 id(发生异常后不要刷新会话)

编辑后不刷新 ALV。为啥?

解决使用this.$router.push()方法页面跳转后不加载列表刷新的方法问题

jqgrid有没有增删改后不刷新表格,而由自己手动刷新的方法?

为啥方法在抛出异常后不需要返回值?

Laravel 5 - 用户在会话生命周期后不注销