我正在编写一个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有机会序列化集合对象之前会话已经关闭,这会导致异常。
所以我试图通过自己明确打开会话来解决这个问题,这会阻止它在每次交易后自动关闭,如下所示:
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
答案 0 :(得分:0)
Take a look a this answer以及以下评论。
问题与你的问题不一样 - 这是你的一般化 - 即如何将JPA(Hibernate)与远程处理相结合(即序列化对象并将它们发送到线上读取)。这不是一个简单而微不足道的问题,尽管这是一个常见的问题。检查我的建议,如果你不明白的话,在这里发表评论。
答案 1 :(得分:0)
我不使用Gilead因此可能是问题的一部分,但我使用ThreadLocal会话。在每个rpc调用中,我将逻辑包装在一个方法中,该方法始终在最终返回之前关闭ThreadLocal会话。第一次请求时,会为该线程打开会话。
但是,您必须在关闭会话之前完全初始化任何代理。最有可能的是,GWT在会话关闭后尝试序列化您的POJO,当它到达代理或惰性集合时,它无意中尝试初始化它。就个人而言,我要么将POJO复制到单独的对象,要么确保我确切地知道哪些字段将被序列化并提前“触摸”它们(例如,通过调用集合上的size())。如果你有一个深层嵌套的对象,那就太难了。
如果有一个GWT钩子允许你在序列化之后但在rpc线程完成之前执行代码,那将是很好的。有可能存在而且我只是不知道它。