保存方法 - 发生异常后不刷新会话
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
inmodels.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(发生异常后不要刷新会话)
解决使用this.$router.push()方法页面跳转后不加载列表刷新的方法问题