1

Hibernateを使用したJavaPersistenceは、関連するエンティティを熱心にフェッチする方法の例を数多く示しています。

  • @org.hibernate.annotations.BatchSizeを関連するクラスに追加する
  • 関連するクラスを参照するフィールドに@org.hibernate.annotations.Fetchを追加します
  • HQLクエリなどで「fetch」キーワードを使用する...

ただし、私の場合は、対象のエンティティクラスへの関連付けを構築する責任がある実行速度の遅いプロセスを扱っています。つまり、実行時に、1つのエンティティにクエリを実行して、他のエンティティの関連付けられたすべてのインスタンスを熱心にフェッチするように要求することはできません。そのような関連付けは存在しないためです。

つまり、プロセスは次のようになります。

public class InitConfig {

    private final SessionFactory sessionFactory;
    private final NodeManager nodeManager;

    public void run() {

        final Configuration config = new Configuration("NewConfiguration", new HashSet<Node> ());
        for(String name : lotsOfNames) {

            //Lots of these queries run slowly
            final Node node = this.nodeManager.getNode(name);
            config.addNode(node);
        }
        this.sessionFactory.getCurrentSession().save(config);
    }
}

関連するDAO(NodeManager)と低速クエリのエンティティ(Node)は次のようになります。

public class NodeManager {

    private final SessionFactory sessionFactory;

    public Node getNode(String name) {

        final Session db = this.sessionFactory.getCurrentSession();
        final Query query = db.createQuery("from NODE where NAME = :name");
        query.setString("name", name);
        return (Node)query.uniqueResult();
    }
}

@Entity(name="NODE")
public class Node {

    @GeneratedValue(strategy=GenerationType.TABLE)
    @Id @Column(name="ID")
    private Long id;

    private @Column(name="NAME", nullable=false, unique=true) String name;

    //Other properties and associations...
}

そして最後に、実行速度の遅いプロセスによって作成されているエンティティは次のとおりです。

@Entity(name="CONFIGURATION")
public class Configuration {

    @Id @GeneratedValue @Column(name="ID")
    private Long id;
    private @Column(name="NAME", nullable=false, unique=true) String name;

    @ManyToMany
    @JoinTable(
        name="CONFIGURATION_NODE",
        joinColumns=@JoinColumn(name="CONFIGURATION_ID", nullable=false),
        inverseJoinColumns=@JoinColumn(name="NODE_ID", nullable=false))
    private Set<Node> nodes = new HashSet<Node> ();

    public void addNode(Node node) {

        this.nodes.add(node);
    }
}

私の質問はこれです:一度にノードの多くのインスタンスを熱心にフェッチするようにHibernateの構成やコードを変更するにはどうすればよいですか?

次の質問は次のようになります。

  • Hibernateの第2レベルのキャッシュはこれに適していますか?もしそうなら、どうすれば設定できますか?
  • そうでない場合、ここで使用できる他のHibernate機能はありますか?

現在、約100,000のノードがあるので、すべてのノードをクエリしてアプリケーションのどこかにキャッシュするというブルートフォースのアプローチを採用するのは気が進まない。それは、ノードの数を増やすことにはならず、重複するように見えるからだ。アプリケーションとHibernateの内部(セッション、第2レベルのキャッシュなど)の間のデータ。

4

1 に答える 1

2

私はあなたがここで何をしようとしているのか100%明確ではありません... Configuration.addNode()(またはあなたが示していない他の方法)はいくつかのビジネスロジックを含みますか?

そうでない場合は、ノードを構成に関連付けるために、いくつかのバッチ更新クエリを実行する方がはるかに良いでしょう。

もしそうなら(つまり、各ノードをロードして検査する必要があります)、次のことができます。

  1. リスト全体lotsOfNamesを、たとえば1000個の名前のバッチに分割します(この番号で遊んで、最適なパフォーマンスが得られるものを確認できます)。
  2. 条件付きクエリを介して、ノードのバッチ全体を一度にロードしname IN(?)ます。
  3. それらを構成に追加します。
  4. セッションをフラッシュします(オプションで、新しいトランザクションをコミット/開始します)。

1000ではなく1つのクエリを実行し、挿入をまとめてバッチ処理するため、はるかに高速になるはずです。

于 2009-09-23T17:29:00.093 に答える