2013-02-01 41 views
0

我试图用HQL创建简单的选择查询。 有一个将用于查询的实体。它看上去像下面这样:具有父子关系的实体(单个表)的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)组成。查询结果应该是没有孩子的父母1和孩子2的父母2。

查询:

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

结果 - 我只获得其中有“1” 孩子的家长为test_id。但即使没有需要的孩子,我也需要所有的父母。 这里有什么错:映射或查询?它应该如何呢?

在此先感谢。

回答

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) 
+0

是的,我试过相同的映射,然后我试图删除双向映射 - 它也适用(不知道如何)。无论如何感谢解释 - 我会照你说的去做。其实我正在寻找正确的查询。我希望可能有办法让父母没有不需要的孩子。但是...感谢您的重播。 –