1

我有一个 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()and后Session.update(),对应Session的ActionQueue为空。但是,事务提交后,我可以在数据库中看到创建的实体。

操作createAcreateB按此顺序调用,无需调试。B当它尝试检索A先前使用条件和方法创建的实例时,在执行创建期间出现错误Session.list()。问题是A找不到的实例。

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

谢谢


编辑:我忘了确切地说它适用于某些机器但不适用于其他机器。而且我看不出这些机器之间有任何区别。

4

2 回答 2

1

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

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

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

  • 查找数据库的事务模式。一些数据库有脏读,没有正确的锁定或同步。检查您是否不小心使用了这种模式。
  • 检查 JDBC 参数(它们可以在 hibernate connection.url 中使用)如果您的数据库有更改时间和同步的参数。
  • 检查您的连接池(对于您正在使用的情况)。
于 2012-06-07T14:25:28.223 回答
1

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

您对 B 的调用有时可能发生在 A 请求的事务结束之前。这就是为什么如果你等待一会儿它会起作用的原因。

尝试在保存调用后添加 session.flush() 。这将强制 Hibernate 将更改持久化到数据库。

于 2012-06-07T14:36:37.153 回答