Hibernate,GWT和Gilead:会话,事务和缓存 [英] Hibernate, GWT and Gilead: sessions, transactions and caches

查看:119
本文介绍了Hibernate,GWT和Gilead:会话,事务和缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个GWT应用程序,在服务器端使用Hibernate。现在,我对使用最少代码将我的对象转移到GWT应用程序的客户端的正确方法感到困惑。我正在使用Gilead来避免在我的域模型中增加两倍的类。[b]

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

  // begin rpc call 
getCurrentSession
beginTransaction
// ...做东西
commit
//会话自动关闭
//结束rpc调用

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

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

  org.hibernate.HibernateException:集合不与任何会话关联
在org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:449)`

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



所以我试图通过明确地打开Sessio来弥补这一点ñ我自己,这可以防止它在每次交易后自动关闭,如下所示:

  openSession 
// begin rpc call
beginTransaction
// ...做东西
commit
//结束rpc调用

//下一个rpc调用
beginTransaction
// ... etc

然而,当我这样做时,我看到与Session对象缓存相关的各种奇怪行为。首先,createQuery()。executeUpdate()似乎不会使会话缓存失效,尽管我已经阅读过它应该使用的各种网站。当我尝试通过调用session.flush(),session.clear()等等的各种置换来尝试解决该问题时,下一个错误是在Gilead或Beanlib内部深入序列化的ClassCastException:null 。



另外,当我尝试这样的事情时:

 客户端从服务器获取对象
客户端修改对象
客户端发送对象返回
服务器调用session.saveOrUpdate()

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



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

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

解决方案

我不使用Gilead,这可能是问题的一部分,但我使用ThreadLocal会话。在每个rpc调用中,我将该逻辑封装在始终在最终返回之前关闭ThreadLocal会话的方法中。第一次请求时,会话将为该线程打开。 然而,在关闭会话之前,您必须完全初始化任何代理。最有可能的是,在会话结束后,GWT试图序列化POJO,当它到达代理或惰性集合时,它会无意中尝试初始化它。就个人而言,我要么将POJO复制到单独的对象中,要么确保我确切知道哪些字段将被序列化,并提前触摸它们(例如,通过调用集合上的size()。如果你有一个深度嵌套的对象是很困难的。



如果有一个GWT钩子让你可以在序列化之后但在rpc线程完成之前执行代码,那将会很不错。可能有,我只是不知道。


I am writing a GWT application, using Hibernate at the server side. Right now, I am entirely confused about the correct way to transfer my objects to the client side of the GWT application in the least amount of code. I am using Gilead to avoid having to double the amount of classes in my domain model [1].

First off, my question is how I should be opening sessions and transactions. Initially, I did this on every RPC server call:

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

Since this opens and closes a Session for every RPC call, does this also create a new connection to the database server every time?

Anyway, as soon as I start using lazily loaded collections, I get the following exception using this pattern:

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

It seems to me that the session is closed before Gilead gets a chance to serialize the collection object and this causes the exception.

So I tried to remedy this by explicitly opening the Session myself, which prevents it from being closed automatically after every transaction, like so:

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

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

However, when I'm doing this, I'm seeing all kinds of funky behavior related to the Session object cache. For one thing, createQuery().executeUpdate() does not seem to invalidate the session cache, although I've read on various sites that it should. When I tried to remedy that by trying to invalidate the session cache by calling various permutations of session.flush(), session.clear() and so on, the next error was a "ClassCastException: null" on serialization deep inside Gilead or Beanlib.

For another thing, when I'm trying something like this:

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

I'm getting an error like "a different object with the same identifier is already in the session cache".

What is the proper way to do set this sort of thing up? How should I scope my sessions and how should I treat the cache? I can't imagine I'm the only one trying this and having problems with it, but good guides seem to be hard to come by.

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

解决方案

I do not use Gilead so that may be part of the problem, but I use ThreadLocal sessions. In each rpc call, I wrap the logic in a method that always closes the ThreadLocal session before the final return. The session is opened for that thread the first time it's requested.

However, you have to fully initialize any proxies before you close the session. Most likely, GWT is trying to serialize your POJO after the session has been closed and when it's gets to a proxy or a lazy collection, it inadvertently tries to initialize it. Personally, I either take the hit of copying the POJOs to separate objects or I make sure I know exactly which fields are going to be serialized and 'touch' them ahead of time (for example, by invoking size() on a collection. But it's difficult if you have a deeply nested objects.

It would be nice if there was a GWT hook that let you execute code after serialization but before the rpc thread completes. It's possible that there is and I just don't know about it.

这篇关于Hibernate,GWT和Gilead:会话,事务和缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆