0

HQL で単純な選択クエリを作成しようとしています。クエリで使用されるエンティティがあります。次のようになります。

@Entity
@Table(name = "my_table")
public class MyTable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "test_id")
    private Long testId;

    @Column(name = "parent_id")
    private Long parentId;

    @OneToMany(mappedBy = "parentId", 
               fetch = FetchType.EAGER, 
               cascade = CascadeType.ALL)
    private Set<MyTable> children = new HashSet<MyTable>();

    //getters and setters
}

階層は単純です。親 (parent_id 値が null) とその子が存在します。だから2レベルだけ。

すべての親とその子を選択するクエリを作成したいのですが、子には特定のtest_idと等しいという条件があります。たとえば、 test_id = 1の子のみが必要です。テーブルは、Child1 を持つ Parent1 ( test_id = 2 ) と Child2 を持つ Parent2 ( test_id = 1 ) で構成されます。クエリの結果は、子のない Parent1 と、Child2 のある Parent2 になります。

クエリ:

from MyTable as myTable left fetch join myTable.children as child 
where child.testId = 1

その結果、 「1」 test_idを持つ子を持つ親のみを取得しています。しかし、必要な子供がいなくても、すべての親に見てもらう必要があります。ここで何が間違っていますか: マッピングまたはクエリ? そして、それは実際にはどうあるべきですか?

前もって感謝します。

4

1 に答える 1

3

あなたのマッピングは間違っています。一方向の OneToMany 関連付けがあります。したがって、明らかに、この関連付けがどのようにマップされているかを Hibernate に伝える必要があります。そして、あなたが言うことは:

@OneToMany(mappedBy = "parentId", ...)

これは、「この双方向の関連付けの反対側を見て、この関連付けがどのようにマッピングされているかを調べてください。私は反対側にすぎません」.

しかし、反対側はありません。あなたの関連付けは一方向です。

マッピングは次のようになります。

@Entity
@Table(name = "my_table")
public class MyTable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "test_id")
    private Long testId;

    @OneToMany(fetch = FetchType.EAGER, 
               cascade = CascadeType.ALL)
    @JoinColumn(name = "parentId")
    private Set<MyTable> children = new HashSet<MyTable>();

    //getters and setters
}

このparentIdフィールドは、children 関連付けのマッピングに既に使用されているため、削除されていることに注意してください。

もう一つの問題はあなたの期待です。クエリは列を返すか、エンティティを返します。親エンティティが返され、このエンティティにその子を要求すると、すべての子が返されます。AN エンティティは、データベースの内容を表します。特定のクエリの結果を表すものではありません。

子供の一部だけが必要な場合にできることは、子供を検索してその親を取得することです。そのためには、関連付けを双方向にする必要があります。

@Entity
@Table(name = "my_table")
public class MyTable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "test_id")
    private Long testId;

    @ManyToOne
    @JoinColumn(name="parentId")
    private MyTable parent;

    @OneToMany(mappedBy="parent",
               fetch = FetchType.EAGER, 
               cascade = CascadeType.ALL)
    @JoinColumn(name = "parentId")
    private Set<MyTable> children = new HashSet<MyTable>();

    //getters and setters
}

クエリは次のようになります。

select child from MyTable child 
left join fetch child.parent
where child.testId = 1

これにより、testId = 1 を持つすべての子とその親が返されます。他のすべての親を取得するには、2 つ目のクエリが必要になります。何かのようなもの

select parent from MyTable parent 
where parent.id not in (
    select parent2.id from MyTable child   
    left join child.parent parent2
    where child.testId = 1)
于 2013-02-01T16:28:25.187 に答える