1

非常に単純な選択 (SELECT h FROM Hero h where h.owner = :player) が n+1 問題を引き起こすという問題があります。クエリは、各ヒーロー エンティティのゲームへの選択をトリガーします。

最初に、選択中に代替クエリを削除するフェッチ タイプ レイジーを追加しました。私のコードでは、IDを取得するためにゲームが1回だけ必要です。これにより、すべてのエンティティに対して再度選択がトリガーされました。

だから私は助けになった結合フェッチを追加しましたが、それは私が必要としない結合を引き起こします! エンティティ全体をフェッチせずに、休止状態のプロキシ オブジェクトに ID を渡すように指示するにはどうすればよいですか?

そこでのヒントを試してみましたが成功しませんでした: http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml

hibernate の @AccessType と javax の @Access はどちらも違いはありません。getId() を呼び出すと、ゲームは常に取得されます。

私が見逃しているアイデアはありますか? 私はこれをかなり頻繁に必要とするので、できれば結合を避けたいと思っています。

挨拶、マルクス

PS: jboss 7 で jpa2 + hibernate 4 を使用しています。

@Entity
@NamedQueries({ 
    @NamedQuery(name = "Hero.findByPlayer", query = "SELECT h FROM Hero h JOIN FETCH h.game where h.owner = :player") 
    })
public class Hero extends GameCharacter implements Serializable {   
    @ManyToOne
    private Player owner;

@Entity
public abstract class GameCharacter extends GameObject implements Serializable {
     ... nothing special in here
}

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class GameObject implements Serializable {
    @Id
    private String id = java.util.UUID.randomUUID().toString();

    @ManyToOne(fetch=FetchType.LAZY)
    protected Game game;

@Entity
public class Game implements Serializable {
    private static final long serialVersionUID = 4379242677193301727L;

    @Id
    private String id = java.util.UUID.randomUUID().toString();
4

1 に答える 1

1

これは、休止状態での遅延読み込みの動作の副作用にすぎません。基本的に、遅延オブジェクトにアクセスすると、データが取り込まれます。id の特別なケースはありません。

ロードをトリガーせずに、実際にゲーム オブジェクトから ID にアクセスできるとは思いません。できることは、getIdentifier メソッドを使用してオブジェクトの ID を hibernate に問い合わせることです。休止状態は単にオブジェクトのメタデータを検索しているだけなので、これはフェッチをトリガーしないと思います。

あるいは、クエリを実行するときにヒーローと一緒にゲーム ID をロードすることもできます。

例えば

SELECT h, h.game.id FROM Hero h where h.owner = :player

現在のクエリのようにヒーローのリストを見つけるのではなく、ペアのリストが返され、各ペアにはヒーローとゲーム ID が含まれます。

ID は HQL で特別に扱われるため、オブジェクトにアクセスしようとしたときに取得しているフェッチまたは結合をトリガーするべきではありません。

于 2012-11-23T09:35:33.933 に答える