【问题标题】:JPA criteria builder: how to replace and cast a string to numeric in order-by?JPA 标准构建器:如何按顺序替换字符串并将其转换为数字?
【发布时间】:2018-08-29 05:17:58
【问题描述】:

有人可以建议我如何使用 JPA Criteria builder API 构建以下查询吗?

SELECT id, name, date, version FROM public.upgradeTable
order by (CAST(replace(version, '.', '')AS numeric)) desc;

请注意,我们的版本列具有“11.0.2.213”、“11.0.2.73”等值 我们需要修剪字符 '.'在版本中,然后将它们转换为数字,然后按 desc 排序。

【问题讨论】:

  • 首先是无效的JPQL,JPQL(或Criteria)中没有“替换”功能。其次,展示您迄今为止尝试过的内容,以及您遇到问题的具体部分
  • 是的,我在那里搜索过,没有替换内部标准生成器。但我们的要求是对这个版本列进行排序。由于版本列是 varchar,它提供了字符串排序。因此,当使用 jpa 时,我们使用 orderList.add(cb.desc(uf.get("version")) 它基于字符串排序并在“11.0.2.213”上方列出“11.0.2.73”。要解决这个问题,我们需要删除“ .” 从版本中将其转换为数字然后排序。描述中给出的查询正在工作......在实际的 postgress 数据库上,我们需要找到任何方式或其他方式在 JPQL 或 java 中的 Critera Builder 中实现这一点。请建议跨度>
  • 我在stackoverflow.com/questions/52054094/…中已经解释过了
  • 所以这是该问题的重复。请不要提出重复的问题
  • 将删除一个。但是你能建议在标准构建器中是否有办法处理这个问题。

标签: java jpa spring-data-jpa criteria builder


【解决方案1】:

目前 JPA 没有用于 replace() 和 cast(string as numeric) 的 API。但如果数据库的可移植性不重要,您可以使用 CriteriaBuilder.function(...) 创建数据库原生函数。

对于 MySQL,您的示例的 order-by 表达式为:

    Expression<String> replacedValue = criteriaBuilder.function("replace", 
            String.class, root.get("version"), criteriaBuilder.literal("."), 
            criteriaBuilder.literal(""));

    Expression<String> lpadValue = criteriaBuilder.function("lpad", 
            String.class, replacedValue, criteriaBuilder.literal(20),
            criteriaBuilder.literal("0"));

    criteriaQuery.orderBy(criteriaBuilder.desc(lpadValue));

CriteriaBuilder.function(...) 不支持 cast(value as type) or convert(value, type) 这样的原生函数。所以使用 lpad(...) 来实现同样的 orderBy 结果。

它适用于 Cmobilecom JPA,这是一种适用于 Java 和 Android 的轻量级 JPA 实现。

免责声明:我是 Cmobilecom JPA 的开发人员。

【讨论】:

  • 嘿约翰感谢您的回复,它对我有用。当我看到您的回复时,我可以弄清楚替换功能。但我无法弄清楚如何实现 lpad 功能。再次感谢您的宝贵回复。
  • 嗨,John,您正确地提到了 CAST 不可用。但是使用 lpad 确实是非常好的建议谢谢
  • 嗨,约翰,我们正在创建它来比较格式为“11.2.2000.3”或“11.2.2000.111”的版本,在这种情况下,lpad 总共 10 个工作正常。但是当比较“11.2.2000.3”和这个“4.200.10.10”时它会失败,因为最终它将比较11220003和42001010。它会认为“4.200.10.10”更大。那么在替换“。”之后,标准构建器是否提供了将其转换为整数的任何功能或方式。请建议
  • 即使在 Criteria API 中有将字符串转换为整数的方法,将“11220003”和“42001010”转换为整数,“4.200.10.10”也会更大。如果我正确理解您的 orderBy 版本,您应该从第一部分开始逐部分比较它们。对于上面的示例,第一部分“11”大于“4”,以“11”开头的版本更大。在 Criteria API 中,有 locate() 和 substring(),但提取 4 个部分可能很复杂。 Oracle 有 regexp_substr()。 MySQL 有 substring_index()。您可能需要为您的数据库创建一个函数。
  • MySQL substring_index() 不完全从字符串中提取一部分。但它可以通过 lpad 达到您的目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2012-05-19
  • 2012-01-26
  • 2011-03-31
相关资源
最近更新 更多