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レベルのキャッシュなど)の間のデータ。