10

我们的设计有一个 jvm,它是一个 jboss/webapp(读/写),用于通过休眠(使用 jpa)将数据维护到数据库。该模型有 10-15 个持久类,关系深度为 3-5 级。

然后我们有一个单独的 jvm,它是使用这些数据的服务器。由于它连续运行,我们只有一个长的数据库会话(只读)。

当前不涉及 jvm 内缓存 - 因此我们手动从另一个 jvm 发出信号。

现在,当 webapp 更改某些数据时,它会向服务器发出信号以重新加载更改的数据。我们发现我们需要告诉 hibernate 清除数据然后重新加载它。仅对数据库进行获取/合并并不能完成这项工作 - 主要是针对层次结构下几层的对象。

关于此设计是否存在根本性错误的任何想法,或者是否有人正在这样做并且在重新加载时使用 hibernate 有更好的运气。

谢谢,克里斯

4

4 回答 4

14

Hibernate 会话将从数据库中读取的所有数据加载到他们所谓的一级缓存中。一旦从数据库中加载了一行,任何后续获取具有相同 PK 的行都将从该缓存返回数据。此外,Hibernate garentees 在单个 Session 中引用具有相同 PK 的对象的相等性。

据我了解,您的只读服务器应用程序永远不会关闭其休眠会话。因此,当读写应用程序更新数据库时,只读服务器上的会话不知道更改。实际上,您的只读应用程序正在加载数据库的内存副本并使用该副本,该副本在适当的时候会变得陈旧。

我可以建议的最简单和最好的做法是根据需要关闭和打开会话。这回避了整个问题。Hibernate Sessions 旨在成为与 DB 进行短期交互的窗口。我同意通过不一次又一次地重新加载对象图来提高性能;但你需要衡量它并说服自己,这是值得的。

另一种选择是定期关闭并重新打开会话。这可确保只读应用程序使用不早于给定时间间隔的数据。但是肯定存在一个只读应用程序处理陈旧数据的窗口(尽管设计保证它最终会获得最新数据)。这在许多应用程序中可能是允许的 - 您需要评估您的情况。

第三种选择是使用二级缓存实现,并使用短期会话。有各种缓存包可以与 Hibernate 一起使用,各有优缺点。

于 2008-09-08T19:45:49.880 回答
5

克里斯,我对你的情况有点困惑。如果我理解正确,您有一个使用 Hibernate 访问共享数据库的 Web 应用程序(读/写)和独立应用程序(只读?)。您对 Web 应用程序所做的更改对独立应用程序不可见。是对的吗?

如果是这样,您是否考虑过使用不同的二级缓存实现?我想知道您是否可以使用由 Web 应用程序和独立应用程序共享的集群缓存。我相信与Hibernate集成的SwarmCache会允许这样做,但我自己没有尝试过。

不过,一般来说,您应该知道给定缓存的内容永远不会知道另一个应用程序的活动(这就是为什么我建议让两个应用程序共享一个缓存)。祝你好运!

于 2008-09-07T21:16:58.717 回答
2

从我的角度来看,您应该将下划线 Hibernate 缓存更改为支持集群模式的缓存。它可以是JBoss CacheSwarm Cache。第一个对数据同步(复制和失效)有更好的支持,也支持JTA。

然后您将能够配置 webapp 和服务器之间的缓存同步。如果您将使用 JBoss Cache,还要查看隔离级别。如果您想从同一会话中获取服务器上的新数据,我相信您应该使用READ_COMMITTED模式。

于 2009-02-22T07:40:25.643 回答
1

最常用的做法是拥有一个容器管理的实体管理器,以便同一个容器中的两个或多个应用程序(即 Glassfish、Tomcat、Websphere)可以共享相同的缓存。但是如果你不使用 Application 容器,因为你使用的是 Play!例如,然后我会在主应用程序中构建一些 Web 服务,以便在缓存中一致地读/写。

我认为使用陈旧的数据会导致灾难。就像 Singletons 变成 Multitons 一样,只读应用程序有时往往是一个写操作。

腰带和背带:)

于 2012-11-27T07:30:21.163 回答