Hibernate漏报读取

时间:2012-06-07 13:53:10

标签: java hibernate

我有一个Web应用程序,它包含一个包含两个操作的Web服务:createAcreateB。为端点注册了一个处理程序。此处理程序打开会话并在收到请求时启动事务。然后执行所请求操作的代码。在发回响应之前,事务已提交,会话已关闭。

createA的代码包括创建A类型的实体并使用Session.save()方法对其进行持久化。在DEBUG模式下,在调用Session.save()之后,我可以看到会话的ActionQueue中有一个插入。

createB的代码包含:

  • 检索先前创建的A
  • 类型的实体
  • 创建引用B实例的实体A(B具有代表关联A的属性)
  • 更新A以引用B
  • 的新实例
  • Session.save()
  • 的新实例调用B
  • Session.update()
  • 的新修改实例调用A

但是,在DEBUG模式下,在调用Session.save()Session.update()之后,相应Session的ActionQueue为空。但是,在事务提交之后,我可以在数据库中看到创建的实体。

在没有DEBUG的情况下,按此顺序调用操作createAcreateB。创建B时,在尝试检索先前使用条件和A方法创建的Session.list()实例时,会出现错误。问题是找不到A的实例。

但是,如果我在DEBUG中重复相同的操作序列或在两个操作的调用之间使用Thread.sleep(15s),则可以找到A的实例。

由于


编辑:我忘了确切地知道它适用于某些机器而不适用于其他机器。我认为这些机器之间没有任何差异。

2 个答案:

答案 0 :(得分:1)

如果对createA和createB使用相同的Hibernate会话,那么它将起作用。您可以在Http会话中存储Hibernate会话以实现此目的(注意同步对会话对象的访问,因为来自同一浏览器会话的请求可以在不同的线程中进行)。

您的问题是,Hibernate为每个会话打开一个新的数据库连接。现在你的数据库似乎没有同步语句。在插入完成之前,选择到达的数据库中可能会发生这种情况。然后,如果发生这种情况,它只取决于所涉及的计算机的速度。使用调试模式或sleep()可以使一台计算机变慢,这样就不再有问题了。

如果您想为这两个程序继续两个不同的会话,您可以

  • 查找数据库的事务模式。某些数据库具有脏读,其中没有正确的锁定或同步。检查您是否意外使用了这种模式。
  • 检查JDBC参数(它们可以在hibernate connection.url中使用),如果有数据库参数可以改变时序和同步。
  • 检查您的连接池(对于您使用的连接池)。

答案 1 :(得分:1)

问题是当您调用Session.save()时,Hibernate不会将实体保存到数据库。它只是准备语句以便稍后执行。当事务结束或刷新会话时会发生这种情况。

您的B号呼叫有时可能会在A请求的交易结束之前发生。这就是为什么如果你等了一会儿就行了。

尝试在保存调用后添加session.flush()。这将强制Hibernate将更改保留到DB。