【问题标题】:Hibernate sort entities by property of children mapped as Map<String, Child>Hibernate 按映射为 Map<String, Child> 的子属性对实体进行排序
【发布时间】:2016-03-21 14:14:48
【问题描述】:

这是我的模型:

@Entity
@Table(name = "parent")
public class Parent {

    ...

    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = { CascadeType.REMOVE}, mappedBy = "parent")
    @MapKeyColumn(name = "key")
    private Map<String, Child> children;

    ...

}

@Entity
@Table(name = "child")
public class Child {

    ...

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Parent parent;

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

    ...

}

该映射很有用,可用于插入、更新、删除和选择实体。

现在我必须根据映射键使用其 children 属性来订购 Parent 实体,类似于 order by parent.children[&lt;particular key&gt;].property asc 子句(我在 HQL 中没有找到)。我也不知道如何使用 Criteria API 来实现这一点。有什么想法吗?

我现在唯一的解决方案是选择按key 过滤并按property 排序的子项,然后在Java 代码中一一获取父项,即使设置了“获取父项”也效率不高。

【问题讨论】:

  • 我不知道它是否有效,但是您是否尝试过在Parent.children 上添加@OrderBy 注释?那么它应该是@OrderBy("property asc")
  • 注解类型OrderBy:指定在检索关联或集合时集合值关联或元素集合的元素的排序。似乎不是我的情况,因为用于对映射集合中的项目进行排序
  • 由于 Map 没有内在顺序,我怀疑使用 JPA 是否可行,因为您不能指定 Hibernate 应该使用可排序的 Map 作为实现。

标签: java hibernate


【解决方案1】:

表创建语句如下:

create table child (id bigint not null, key varchar(255), property varchar(255), parent_id bigint, primary key (id))
create table parent (id bigint not null, primary key (id))

对父表的 parent_id 有约束。

向后工作,sql 看起来很简单:

select p.* from parent p join child c on p.id = c.parent_id where c.key = 'c1' order by c.property asc;

所以 JPQL 和 Criteria 查询也应该是直截了当的:

List<Parent> po1 = em.createQuery("select p from Parent p join p.children c where c.key='c1' order by c.property asc", Parent.class).getResultList();
System.out.println(po1);

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> cq = cb.createQuery(Parent.class);
Root<Parent> p = cq.from(Parent.class);
Join<Parent, Child> c = p.join("children");
cq.select(p).where(cb.equal(c.get("key"), "c1")).orderBy(cb.asc(c.get("property")));
List<Parent> po3 = em.createQuery(cq).getResultList();
System.out.println(po3);

为 Parent 创建一个 toString 方法:

public String toString() {
    return "Parent:"+id+":"+children;
}

和孩子:

public String toString() {
    return "Child:"+id+":"+key+":"+property;
}

这给了我以下输出:

Hibernate: select parent0_.id as id1_1_ from parent parent0_ inner join child children1_ on parent0_.id=children1_.parent_id where children1_.key='c1' order by children1_.property asc
[Parent:4:{c1=Child:5:c1:0}, Parent:1:{c1=Child:2:c1:1}]
Hibernate: select parent0_.id as id1_1_ from parent parent0_ inner join child children1_ on parent0_.id=children1_.parent_id where children1_.key=? order by children1_.property asc
[Parent:4:{c1=Child:5:c1:0}, Parent:1:{c1=Child:2:c1:1}]

在我看来,它是由 key 为特定值的子属性排序的父母。

【讨论】:

    猜你喜欢
    • 2015-06-19
    • 2015-01-18
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    相关资源
    最近更新 更多