4

I'm dealing with a legacy Java application with a large, fairly messy codebase. There's a fairly standard 'User' object that gets stored in the HttpSession between requests, so the servlets do stuff like this at the top:

HttpSession session = request.getSession(true);
User user = (User)session.getAttribute("User");

The old user authentication layer (which I won't describe; suffice to say, it did not use a database) is being replaced with code mapped to the DB with Hibernate. So 'User' is now a Hibernate entity.

My understanding of Hibernate object life cycles is a little fuzzy, but it seems like storing 'User' in the HttpSession now becomes a problem, because it will be retrieved in a different transaction during the next request. What is the right thing to be doing here? Can I just use the Hibernate Session object's update() method to reattach the User instance the next time around? Do I need to?

4

3 に答える 3

2

要求と応答のサイクルごとに新しい休止状態セッションを作成していると仮定すると、分離されたオブジェクトを新しい休止状態セッションにマージすることは可能ですが、このアプローチは完全に避けます。

代わりに、受信リクエストごとに休止状態を介してユーザーを検索するために使用できるキーを HttpSession に保存してみてください。代わりに HttpSession に格納できるものを取得するためにデータベースにアクセスすることによるパフォーマンスへの影響が心配な場合でも、恐れることはありません。データベースへのアクセス回数を減らすために、hibernate でサポートされているキャッシュ フレームワークをいつでも使用できます。パフォーマンスを向上させるもう 1 つの方法は、楽観的ロックを使用することです。

休止状態のソースは見ていませんが、休止状態は「アイデンティティ マップ」パターンを使用していると思います。これは、エンティティの ID をマップのキーとして使用し、関連付けられたエンティティ オブジェクトをマップの値として使用するマップです。休止状態のセッションからエンティティが取得されるたびに、休止状態はセッションの ID マップを調べて、存在するかどうかを確認します。そこにある場合は、マップからエンティティを返します。存在しない場合は、データベースからエンティティを取得してマップに配置し、エンティティを返します。これは、特定の hibernate セッションの同じキー (つまり、id、userId など) を持つ特定のユーザーにアクセスする連続したクエリが、同じユーザー オブジェクトへの参照を受け取ることを意味します。したがって、各クエリは、に対して行われた変更を「見る」ことができます。他のクエリによる User オブジェクト。このため、受信リクエストごとに新しい休止状態セッションを作成することが絶対に必要です。これにより、特定のユーザーに対する同時リクエストが共通のユーザー オブジェクトでそれぞれのスレッドをロックする必要がなくなります。異なる Hibernate セッションはそれぞれ独自の ID マップを持つため、同じ User オブジェクトへの参照は返されません。

User オブジェクトを HttpSession から hibernate セッションにマージしようとすることで、基本的に hibernate の IdentityMap を直接操作しようとしており、hibernate が「考えている」ものを別のものに置き換えます。当然のことながら、これは問題を引き起こす可能性があります。私が言ったように、切り離されたオブジェクトを休止状態のセッションに戻すことは可能ですが、私はそれを避けます。どんなアプローチでも頑張ってください。

以下を読むことを強くお勧めします。あなたの場合は、特に長い会話と切り離されたオブジェクトに関するセクションです。

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html

于 2010-07-22T09:24:28.343 に答える
0

Use session.merge(..)

(From Session's docs):

The state of a transient or detached instance may also be made persistent as a new persistent instance by calling merge().

Just be sure to override hashCode() and equals() properly.

于 2010-05-29T18:30:00.250 に答える
0

Depends on if the user changes during the session, or if you just want the id, name, etc. for a quick lookup. You can always merge() the user from the db to have it in the session again.

You don't need to merge the user everytime, because its a database hit which you don't always need. But with merge, you reattach the user to the current session.

于 2010-05-29T18:30:25.137 に答える