JPA:如何对实体中的 Set 字段进行排序?

2024-04-06

我正在使用 Spring 3.2.11.RELEASE、Hibernate 4.3.6.Final 和 JPA 2.1。我有以下具有以下字段的实体...

@Entity
@Table(name = "user")
public class User implements Serializable, Comparable<User>
{
    …
    @ManyToMany
    @JoinTable(name = "user_organization", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ORGANIZATION_ID") })
    @LazyCollection(LazyCollectionOption.FALSE)
    @SortNatural
    private SortedSet<Organization> organizations;

上面,组织的排序是通过组织的名称字段完成的。当我运行 JPA 查询来检索 User 对象时,我想根据与其关联的组织的有序列表进行排序。我已经尝试过这个……

final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
final CriteriaQuery<User> criteria = builder.createQuery(User.class);
…
final SetJoin<User, Organization> orgsJoin = orderByRoot.join(User_.organizations, JoinType.LEFT);
orderByExpr = orgsJoin.get(Organization_.name);
criteria.orderBy(builder.asc(orderByExpr);

但它不适用于用户与多个组织关联的情况 - 有时,列表中按字母顺序排列较低的组织的用户会先于正确的用户返回。如果不编写一大堆本机 SQL,我如何使用 JPA/CriteriaBuilder 解决这个问题?

Edit:这是我想要的一个例子。我正在寻找独特的用户。

  • 用户A拥有组织“AAA大楼”和“ZZZ大楼”
  • 用户B只有“MMM大厦”的组织
  • 用户C拥有组织“CCC大楼”和“VVV大楼”
  • 用户 ID 具有组织“AAA Building”和“MMM Building”

我想要用户 D、用户 A、用户 C 和用户 B,因为用户 A 的组织的串联按字母顺序排列低于用户 C 的组织的串联,而用户 C 的组织的串联按字母顺序又低于用户 B 的组织。


您无法为实体编写此类查询。如果您使用本机 SQL,您可以通过 user.id 按组织名称进行 GROUP BY,但这不是您想要的。

您可以简单地获取加入用户和组织:

final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
final CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);
Fetch<User, Organization> organizations = root.fetch("organizations");
criteria.select(c);
TypedQuery<User> query = em.createQuery(criteria);
List<User> users = query.getResultList();

并在内存中对它们进行排序:

Collections.sort(users, new Comparator<User>() {
    @Override
    public int compare(User user1, User user2) {
        SortedSet<Organization> organizations1 = user1.getOrganizations();
        SortedSet<Organization> organizations2 = user2.getOrganizations();

        if(organizations1.isEmpty()) {
            if(organizations2.isEmpty()) {
                return 0;
            } else {
                return -1;
            }
        } else {
            if(organizations2.isEmpty()) {
                return 1;
            } else {
                Organization o1 = organizations1.first();
                Organization o2 = organizations2.first();
                return o1.compareTo(o2);
            }
        }
    }
});

Update

如果您不想获取内存中的所有内容进行排序,那么我认为仅使用 JPQL 或 Criteria API 是不可能的。

假设组织名称是 VARCHAR(50),我们需要首先使用右填充,然后我们需要运行group_concat首先原生查询:

PostgreSQL

SELECT o.user_id, 
       string_agg(RPAD(o.name, 50) ORDER BY o.name) as ordr
FROM Organization o
GROUP BY o.user_id
order by ordr   

MySQL

SELECT o.user_id, 
       group_concat(RPAD(o.name, 50) ORDER BY o.name) as ordr
FROM Organization o
GROUP BY o.user_id
order by ordr

对 user_id 进行排序后,您可以简单地将 user_ids 提取到List<Long>然后运行第二个 JPQL 查询来获取用户:

List<Long> userIds = ...;

TypedQuery<User> q = em.createQuery(
    "select u " +
    "from User u " +
    "where u.id in :userIds "
, User.class);

q.setParameter("userIds", userIds);
List<User> users = q.getResultList();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JPA:如何对实体中的 Set 字段进行排序? 的相关文章

随机推荐

  • 如何在 Specs2 (Scala) 中显示自定义失败消息?

    例如 对于这样的代码 myNum must beEqualTo SOME INTERESTING TEXT 该消息将类似于以下内容 java lang Exception ArrayBuffer doesn t have size 1 bu
  • 枚举实用程序库

    我正在寻找一个开源库或用于在 Net 中使用枚举类型的示例 除了人们用于 Enum 的标准扩展 TypeParse 等 之外 我还需要一种方法来执行操作 例如返回给定枚举值的 Description 属性值或返回具有 Description
  • 计算加速度(驾驶汽车)

    我正在尝试像应用程序 Dynolicious 一样复制加速度计算 但我不确定该去哪里计算 我用吗Core Motion或者我使用其他数字进行计算 我尝试过使用Core Motion s userAcceleraion值 但它根本不像我正在寻
  • CSS 从中心过渡到右下角

    我有一个要求 其中容器在整个页面上伸展 当我单击容器时 它应该变小 这应该发生在动画中 我尝试了 css 过渡 它将拉伸的元素动画到顶部 慢慢缩小到提供的尺寸 同时向右上角移动 但我想要的是 中间缩小 然后通过动画移动到页面右下角 Fidd
  • 在 Jython 中使用多处理 2.6.2.1 包

    我是 Jython Python 世界的新手 我正在尝试在 Jython 中安装多处理包 但是我收到了来自 easy install 的以下返回消息 Setup script exited with error Compiling exte
  • 无法获取 ZeroMQ python 绑定来通过 IPC 接收消息

    我正在尝试通过 IPC 实现 PUB SUB 如果我更改下面的代码 以便订阅者绑定到 tcp 5000 并且发布者连接到 tcp localhost 5000 它可以工作 但我无法让它通过 IPC 工作 我究竟做错了什么 订阅者 py im
  • JQuery UI 加载事件?

    有没有办法不仅检测 jquery UI 是否加载 而且在加载时触发一个事件 现在 我将代码包装在 document ready 函数中 但有时 UI 代码会出错 因为 UI 库未完全加载 所有内容都按正确的顺序加载 该代码在 99 的情况下
  • 如何使用 https 运行 Vue.js 开发服务?

    我正在使用 Vue cli 使用 webpack 模板创建 vue 项目 如何在开发中使用 https 运行它 npm run dev 在最新的vuejs 截至2018年5月7日 中 需要在项目根目录下添加一个 vue config js
  • 为什么我的 Express 路由器中间件没有定义 req.route?

    我正在尝试使用路由器中间件来获取以下值请求路由 https expressjs com en api html req route 我有一些像这样的简单代码 服务器 js import api from api app use api ap
  • webView:didFailLoadWithError -1004: 在 Phonegap ios 中连接 google plus 时无法连接到服务器

    在获取配置文件数据之前接受 google plus 身份验证时 我收到 webView didFailLoadWithError 1004 无法连接到服务器 错误 这些代码之前可以正常工作 现在我面临这些错误 不知道为什么我无法连接 请帮助
  • 使用鼠标光标捕获屏幕截图

    我使用以下代码在 Windows 上获取屏幕截图 hdcMem CreateCompatibleDC hdc int cx GetDeviceCaps hdc HORZRES int cy GetDeviceCaps hdc VERTRES
  • 正确的原型继承

    所以我真的查遍了互联网 发现了许多在 javascript 中设置原型继承的不同方法 其中一些使用call 其中一些使用以下语法 var rabbit prototype new Animal 有些在更改原型后更改构造函数 有些则不更改 有
  • vim :AnsiEsc - 如何默认打开它们?

    我有带有彩色日志条目的日志文件 假设扩展名为 smt2 其中颜色由 ansi 转义码定义 我安装了vim插件基于AnsiEsc vim http www vim org scripts script php script id 302 现在
  • awk 解析文件名并将结果添加到每行末尾

    我有许多名称相似的文件 例如 DWH Export AUSTA 20120701 20120731 v1 1 csv 397 dat 2012 10 02 04 01 46 out DWH Export AUSTA 20120701 201
  • 人类友好的二进制编码

    不久前 我发现一个网站描述了一种对人类友好的二进制到文本编码 例如 在输入 用于解码 时 它接受 0 o 和 O 全部作为相同的值 因为人们往往很容易混合这些字符 不幸的是我不记得它是怎么叫的 编辑 这就是我正在寻找的 其他Base32 的
  • retq 和 ret 有什么区别?

    让我们考虑以下程序 它计算参数的无符号平方 global foo text foo mov rdi rax mul rdi ret 这是正确编译的as 但反汇编为 0000000000000000
  • 如何设置iPhone振动时长?

    我正在使用 AudioServicesPlaySystemSound 来调用振动函数 AudioServicesPlaySystemSound kSystemSoundID Vibrate 有什么办法可以设置振动的持续时间吗 我知道默认持续
  • ASP .NET 5 MVC 6 Identity 3 角色声明组 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我目前正在寻找一种解决方案 以在带有 Identity 3 的 ASP NET 5 MVC 6 中使用高级角色 组权限管理 我启动了一
  • Spring MVC 返回自定义 HTTP 状态代码(无错误)

    在 Spring MVC RequestMapping 注释中 我返回 JSP 页面名称作为结果 这将返回 HTTP 状态代码 200 OK 如何将此状态代码更改为 201 创建之类的内容 ResponseStatus 不起作用 另外 Ht
  • JPA:如何对实体中的 Set 字段进行排序?

    我正在使用 Spring 3 2 11 RELEASE Hibernate 4 3 6 Final 和 JPA 2 1 我有以下具有以下字段的实体 Entity Table name user public class User imple