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 值为空)和他们的孩子。所以只有两个层次。

我想创建选择所有父母和他们的孩子的查询,但是孩子有一个条件:它应该等于特定的 test_id。例如,要求只有test_id = 1的孩子。表由 Parent1 和 Child1 ( test_id = 2 ) 和 Parent2 和 Child2 ( test_id = 1 ) 组成。查询结果应该是 Parent1 没有孩子,Parent2 有 Child2。

询问:

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字段已被删除,因为它已用于映射子关联。

另一个问题是你的期望。查询返回列,或者返回实体。如果它返回一个父实体并且您向该实体询问其子实体,则将返回所有子实体。一个实体代表数据库中的内容。它不代表特定查询的结果。

如果您只想拥有一些孩子,您可以做的是寻找孩子,并找到他们的父母。为此,您需要使关联是双向的:

@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 的孩子以及他们的父母。您将需要第二个查询来获取所有其他父母。就像是

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 回答