0

我正在编写一个 GWT 应用程序,在服务器端使用 Hibernate。现在,我完全不知道用最少的代码将我的对象传输到 GWT 应用程序客户端的正确方法。我正在使用 Gilead 以避免将我的域模型中的类数量增加一倍 [1]。

首先,我的问题是我应该如何打开会话和交易。最初,我在每个 RPC 服务器调用上都这样做:

// begin rpc call
getCurrentSession
beginTransaction
// ...do stuff
commit
// session is automatically closed
// end rpc call

由于这会为每个 RPC 调用打开和关闭一个 Session,这是否也会每次都创建一个到数据库服务器的新连接?

无论如何,一旦我开始使用延迟加载的集合,我就会使用这种模式得到以下异常:

org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:449)`

在我看来,在 Gilead 有机会序列化集合对象之前会话已关闭,这会导致异常。

所以我试图通过自己显式打开 Session 来解决这个问题,这样可以防止它在每次交易后自动关闭,如下所示:

openSession
// begin rpc call
beginTransaction
// ...do stuff
commit
// end rpc call

// next rpc call
beginTransaction
// ...etc

但是,当我这样做时,我看到了与 Session 对象缓存相关的各种时髦行为。一方面, createQuery().executeUpdate() 似乎并没有使会话缓存无效,尽管我已经在各个站点上阅读过它应该这样做。当我试图通过调用 session.flush()、session.clear() 等的各种排列来使会话缓存无效来解决这个问题时,下一个错误是在 Gilead 或 Beanlib 深处的序列化上出现“ClassCastException:null” .

另一方面,当我尝试这样的事情时:

clients get an object from the server
client modifies object
client sends object back
server calls session.saveOrUpdate()

我收到一个错误,例如“具有相同标识符的不同对象已经在会话缓存中”。

设置这种事情的正确方法是什么?我应该如何确定我的会话范围以及我应该如何处理缓存?我无法想象我是唯一一个尝试这个并遇到问题的人,但似乎很难找到好的指南。

[1] http://code.google.com/webtoolkit/articles/using_gwt_with_hibernate.html

4

2 回答 2

0

我不使用 Gilead,所以这可能是问题的一部分,但我使用 ThreadLocal 会话。在每个 rpc 调用中,我将逻辑包装在一个始终在最终返回之前关闭 ThreadLocal 会话的方法中。第一次请求时为该线程打开会话。

但是,您必须在关闭会话之前完全初始化所有代理。很可能,GWT 在会话关闭后尝试序列化您的 POJO,当它到达代理或惰性集合时,它无意中尝试初始化它。就个人而言,我要么将 POJO 复制到单独的对象中,要么确保我确切知道哪些字段将被序列化并提前“触摸”它们(例如,通过在集合上调用 size()。但是如果你有一个深度嵌套的对象,这很困难。

如果有一个 GWT 钩子可以让您在序列化之后但在 rpc 线程完成之前执行代码,那就太好了。有可能有,我只是不知道。

于 2010-01-07T20:27:07.837 回答
0

看看这个答案和下面的评论。

那里的问题与您的问题不同 - 它是您的概括 - 即如何将 JPA(Hibernate) 与远程处理相结合(即序列化对象并将它们发送到线上读取)。这不是一个简单而微不足道的问题,尽管它是一个常见的问题。在那里查看我的建议,如果您有不明白的地方,请在此处发表评论。

于 2010-01-07T19:43:52.183 回答