【问题标题】:How do I express this ORDER BY clause in JPA?如何在 JPA 中表达这个 ORDER BY 子句?
【发布时间】:2013-08-30 08:57:34
【问题描述】:

我正在使用 JPA 2.0、Hibernate 4.1.0.Final 和 MySQL 5.5.27。我正在尝试将本机 MySQL 查询转换为 CriteriaBuilder 查询。

    final Query query = m_entityManager.createNativeQuery(
            "SELECT user_name FROM users WHERE user_name like ? ORDER BY convert(REPLACE(user_name, ?, ''), signed) DESC LIMIT 1")
            .setParameter(1, userNamePrefix.toLowerCase() + "%")
            .setParameter(2, userNamePrefix);

除了我的子句的“ORDER BY”部分之外,我能够找出每个部分。这是没有 ORDER BY 子句的转换后的查询...

    final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
    final CriteriaQuery<User> criteria = builder.createQuery(User.class);
    final Root<User> user = criteria.from(User.class);
    criteria.where(builder.like(user.get(User_.userName), username + "%"));
    final TypedQuery<User> query = m_entityManager.createQuery(criteria);

知道如何将“ORDER BY convert(REPLACE(user_name, ?, ''), signed)” 写为 JPA?

编辑:我正在尝试下面的“函数”建议,但似乎没有办法让函数的“签名”部分不带引号出现。我尝试了以下...

    final Expression<String> usernamePrefixExpr = builder.literal(userNamePrefix);
    final Expression<String> emptyStrExpr = builder.literal("");
    final Expression<String> replaceFn = builder.function("REPLACE", String.class, user.get(User_.userName), usernamePrefixExpr, emptyStrExpr);
    final Expression<String> signedExpr = builder.literal("signed");
    final Expression<String> convertExpr = builder.function("CONVERT", String.class, replaceFn, signedExpr);
    criteria.orderBy(builder.desc(convertExpr));

但是“签名”被替换为“'签名'”,这不起作用。

【问题讨论】:

  • 为什么不使用原生查询呢?我认为如果您使用 mysql 特定功能,不使用本机查询没有优势(我认为本机查询支持仅针对此类问题实现)

标签: mysql hibernate jpa sql-order-by jpa-2.0


【解决方案1】:

这会很难看,但你应该可以使用 CriteriaBuilder 'function()' 方法来做到这一点。

【讨论】:

  • 我尝试了“函数”,但我似乎无法准确翻译我表达的“签名”部分。
  • 我认为function 方法的问题在于它假定所有函数参数都是最终计算为 int 或 string 或类似内容的表达式,但不是关键字。另一种非常丑陋的方法可能是将强制转换封装到 mysql 函数中。 G。命名castStringToInt,然后通过JPA function 语法调用它。但是除了增加对存储函数的依赖外,在结果集较大的情况下,这可能会对性能产生不良影响。
  • 这个“castStringToInt”函数是我要编写的,还是我可以使用 MySQL 的内置函数?我不想编写任何自定义 MySQL 代码,但如果这是这里唯一的解决方案,那就这样吧。
【解决方案2】:

使用replaceFn.as(Integer.class)而不是builder.function("CONVERT", String.class, replaceFn, signedExpr)将问题中最后一个代码块的代码更改为:

final Expression<String> usernamePrefixExpr = builder.literal(userNamePrefix);
final Expression<String> emptyStrExpr = builder.literal("");
final Expression<String> replaceFn = builder.function("REPLACE", String.class, user.get(User_.userName), usernamePrefixExpr, emptyStrExpr);
final Expression<Integer> convertedExpr = replaceFn.as(Integer.class);
criteria.orderBy(builder.desc(convertedExpr));

编辑 这可能不起作用,因为Javadoc 声明“运行时类型未更改”。

【讨论】:

  • 嗨,我不明白你的意思。 Java 代码会变成什么?
  • 感谢您的澄清。运行此程序时,我得到 Hibernate 运行时异常,“java.lang.IllegalArgumentException: org.hibernate.QueryException: cast() 需要两个参数 [select generatedAlias0 from org.mainco.subco.user.domain.User as generatedAlias0 where ( generatedAlias0 .userName like :param0 ) 和 ( generatedAlias0.url=:param1 ) 按 cast(REPLACE(generatedAlias0.userName, :param2, :param3) as integer) desc]" 排序。
猜你喜欢
  • 2018-04-20
  • 2017-05-04
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
相关资源
最近更新 更多