2011-12-14 11 views
0

JPA/JPQL:単方向木のルート要素を見つける。JPA/JPQL:単方向木のルート要素を見つける

次の問題の名前付きクエリを作成するには、いくつかの助けが必要です。

私はエンティティ(TNode)の定義を次の(簡略化した)ものとし、JPA経由で保存/読み込みできます。 エンティティは単方向であるため、子は親を知らない!

今、すべてのルート要素を取得するために名前付きクエリを作成しようとしています。

私はJPA 2.0(Hibernate)を使用し、インターネットでいくつかのヒントを見つけました。その単方向リンクがサポートされています。

2つのツリーを作成してdbに保存するには、単純なJUnit(4)も付属しています。私はすべての主張を取り除いた。私はJUnitのを実行した場合

、表が期待通りになります。

ID NAME CHILDS_ID 
1 A1 (null) 
2 A11 1 
3 B1 (null) 
4 B11 3 

私は、同じテーブル内の自己参照を持つように@JoinColumnを追加しました。単純なSQLの場合、問題 は簡単です(WHERE childs_id = null)。しかし、これをJPQLでどのように書く必要がありますか?

お返事ありがとうございます。

ウーヴェ

ここ
@Entity 
@Table(name = "TNode") 
@NamedQueries({ @NamedQuery(name = "getRootNodes", query = "FROM TNode tnode ......."), }) 
public class TNode implements JPAObject { 
    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    @OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE }) 
    @JoinColumn 
    private Set<TNode> childs = new HashSet<TNode>(); 

    // JPA only 
    private TNode() { 
    } 

    public TNode(String name) { 
    this.name = name; 
    } 

    public void add(TNode tNode) { 
    childs.add(tNode); 
    } 

    @Override 
    public Integer getId() { 
    return id; 
    } 

    @Override 
    public String getName() { 
    return name; 
    } 
} 

簡素化JUnitの

@RunWith(Arquillian.class) 
public class TNodeTest { 
    @Deployment 
    public static Archive<?> createTestArchive() { 
    //@formatter:off 
    Archive<?> archive = ShrinkWrap.create(WebArchive.class, "test.war") 
     .addPackages(true, DummyInterfaceForTest.class.getPackage()) 
     .addAsLibraries(FindMavenArtifact.find("com.thoughtworks.xstream:xstream:1.4.2")) 
     .addAsLibraries(FindMavenArtifact.find("xmlpull:xmlpull:1.1.3.1")) 
     .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml") 
     .addAsResource("import.sql", "import.sql") 
     .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); 
    //@formatter:on 
    System.out.println(archive.toString(true)); 
    return archive; 
    } 

    @Inject 
    @DAO.DAOType(type = DAO.MODE.STATELESS) 
    private DAO<JPAObject> dao; 

    @Test 
    public void testMutipleRoots() throws Exception { 
    TNode root; 

    root = new TNode("A1"); 
    root.add(new TNode("A11")); 

    dao.saveOrUpdate(root); 

    root = new TNode("B1"); 
    root.add(new TNode("B11")); 

    dao.saveOrUpdate(root); 
    } 
} 
+1

あなたはこのアソシエーション双方向をしていないことにより、必要以上にそれが難しくなっています。親フィールドは公にアクセス可能である必要はない。しかし、そのようなクエリのために本当に役立つでしょう。 –

答えて

1

私はJPQLについて少し読んだ後自分で解決策を見つけました。

(サブ)のクエリは、問題を解決:

query = "SELECT node FROM TNode node WHERE node.id NOT IN (SELECT DISTINCT child.id FROM TNode node, IN(node.childs) child)"), }) 
関連する問題