各行にその親への参照が含まれ、同じテーブル内の別の行を参照する単純な隣接モデルを使用すると、JPAとうまく連携しません。これは、JPAがOracleCONNECTBY句またはSQL標準のWITHステートメントを使用したクエリの生成をサポートしていないためです。これらの2つの句のいずれかがないと、隣接モデルを有用にすることは実際には不可能です。
ただし、この問題をモデル化するには、この問題に適用できる他のアプローチがいくつかあります。1つ目は、マテリアライズドパスモデルです。これは、ノードへのフルパスが単一の列にフラット化される場所です。テーブル定義は次のように拡張されます。
CREATE TABLE node (id INTEGER,
path VARCHAR,
parent_id INTEGER REFERENCES node(id));
ノードのツリーを挿入するには、次のようになります。
INSERT INTO node VALUES (1, '1', NULL); -- Root Node
INSERT INTO node VALUES (2, '1.2', 1); -- 1st Child of '1'
INSERT INTO node VALUES (3, '1.3', 1); -- 2nd Child of '1'
INSERT INTO node VALUES (4, '1.3.4', 3); -- Child of '3'
したがって、ノード '1'とそのすべての子を取得するには、クエリは次のようになります。
SELECT * FROM node WHERE id = 1 OR path LIKE '1.%';
これをJPAにマップするには、「path」列を永続オブジェクトの属性にするだけです。ただし、「パス」フィールドを最新の状態に保つには、簿記を行う必要があります。JPA/Hibernateはこれを行いません。たとえば、ノードを別の親に移動する場合は、親参照を更新し、新しい親オブジェクトから新しいパス値を決定する必要があります。
もう1つのアプローチは、入れ子集合モデルと呼ばれ、少し複雑です。おそらく、(私が逐語的に追加するのではなく)その創始者によって最もよく説明されています。
ネストされた間隔モデルと呼ばれる3番目のアプローチがありますが、これは実装するストアドプロシージャに大きく依存しています。
この問題のより完全な説明は、The ArtofSQLの第7章で説明されています。