【问题标题】:HQL query for the Entity (single table) with parent-children relations具有父子关系的实体(单表)的 HQL 查询
【发布时间】:2013-02-01 15:59:06
【问题描述】:

我正在尝试使用 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 孩子的父母。但即使没有需要的孩子,我也需要所有的父母看看。 这里有什么问题:映射或查询?它实际上应该是怎样的?

提前致谢。

【问题讨论】:

    标签: java hql hibernate-annotations


    【解决方案1】:

    您的映射错误。您有一个单向的 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)
    

    【讨论】:

    • 是的,我尝试了相同的映射,然后我尝试删除双向映射 - 它也可以正常工作(不知道如何)。无论如何,谢谢你的解释——我会照你说的做的。实际上,我一直在寻找正确的查询。我想也许有一种方法可以让父母没有不需要的孩子。但是...感谢您的重播。
    猜你喜欢
    • 2011-12-17
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多