2011-12-08 24 views
0

我有一个GWT应用程序,它使用休眠来连接到postgres数据库。当我在更快的服务器上运行tomcat中的应用程序时,我注意到了一个问题。Postgres保存数据比休眠读取值更慢

我的应用程序中的一个视图从数据库加载旧数据。那么发生了什么?在视图中,用户可以输入一些数据,然后他点击保存按钮。这会导致一个异步调用,通过休眠将数据保存到postgres中。只要我在代码中执行commit()(我将lazy update设置为false),我就从异步调用返回,然后对视图进行刷新(=从db重新加载数据并显示它)。这导致重新读取来自db的数据。但是,该视图有时会显示旧数据。然后我再次刷新视图,我可以看到正确的当前数据。我的猜测是,hibernate的commit()函数导致异步调用,因此我比第一次异步调用(当用户点击保存按钮时)早一些回来,而不是将数据保存到postgres。因此该视图加载旧数据。

有没有人有类似的问题,休眠和postgres?

回答

0

您的解释不正确。 Hibernate事务的提交不会写入并提交到数据库,如果提交成功,那么数据将在数据库中提交。

您所看到的来自其他地方:浏览器缓存或二级缓存(如果配置不正确(例如,只读模式))。

另一种解释是,第二个异步调用在发送到服务器之前不会等待第一个异步调用完成。

+0

第一次异步调用在调用commit()完成时完成。但是,如果函数commit()正在另一个线程中执行,那么可能会导致该问题。浏览器无法缓存数据,因为每次我从数据库显式加载数据。 – mkn

+1

提交不是异步的。如果是的话,它不会再被称为交易。 –

2

Hibernate的二级缓存并不捕获通过视图,原生查询等发生的基础实体发生的数据库更新。我会说你被这个咬伤了,并且需要显式地使缓存失效当你知道你已经破坏它,或需要禁用它。

另一种可能性是,您正在使用SERIALIZABLE事务隔离模式,并且打开一个旧事务的连接。假设您的应用程序正在从连接池或应用程序的其他部分获取连接,并且该连接已经在写入您正在尝试阅读的数据之前进行了打开事务。如果是这样的话,你会看到一个旧的快照。这不应该发生,但有问题的应用程序可以返回与池的打开事务的连接,并且池可能未设置为自动关闭并重置它们,或者您可能没有使用正确的连接池。

在这两者中,我认为Hibernate缓存问题更可能是罪魁祸首。

+0

谢谢你分享你的想法。我可以问你我需要禁用缓存吗?这是一个普通的配置,还是可以按照每个表格进行管理? – mkn

+1

@mkn:请参阅Hibernate文档中的“第二级缓存”。您可以通过属性将其设置在持久性单元级别。具体如何根据版本以及如何使用Hibernate来直接或通过JPA的persistence.xml来变化版本。 如果禁用二级缓存可修复您的问题,则不一定要保留该问题。找出哪些查询或多个查询绕过缓存,并查看是否可以在查询运行后将其刷新或使其中的某些查询无效,以便您在其余时间获得好处。 –

+0

你有没有这样的运气? –