java - 如何通过条件查询调用使用mysql关键字作为参数的函数?

标签 java jpa criteria-api

我正在使用 mysql 和 jpa 规范查询。 我想知道如何调用使用 mysql 关键字作为参数的函数。

示例如下:

select * from schema3.countries order by convert(name using GBK);

使用 usingGBK 关键字作为参数的 convert 方法。

我想通过条件查询调用convert函数。

我尝试了以下方法,但它对我不起作用。

Expression expression = join.get(Country_.NAME);
                Expression orderExpression = builder.function(
                        "convert",
                        String.class,
                        expression,
                        builder.literal("USING GBK")
                );

Path path = join.get(Country_.NAME);

                String countryNameAlias = path.getAlias();
                Expression orderExpression = builder.function(
                        "convert",
                        String.class,
                        builder.literal(countryNameAlias + " USING GBK")
                );

变量countryNameAlias为空,因此它不起作用。

这是错误:

Hibernate: select expert0_.id as id1_14_, expert0_.code as code2_14_, expert0_.created_at as created_3_14_, expert0_.expert_information as expert_i4_14_, expert0_.meta_data_of_the_expert_information as meta_dat5_14_, expert0_.motherland as motherla8_14_, expert0_.number_of_applications as number_o6_14_, expert0_.updated_at as updated_7_14_, JSON_EXTRACT(expert0_.expert_information, '$.basicInformation.birthDate') as formula4_, case
           when
               JSON_EXTRACT(expert0_.expert_information, '$.basicInformation.gender') = 'MALE'
            then 0
else 1 end as formula5_, JSON_EXTRACT(expert0_.expert_information, '$.basicInformation.nameEN') as formula6_, convert(JSON_EXTRACT(expert0_.expert_information, '$.basicInformation.nameZH') using GBK) as formula7_ from expert expert0_ left outer join expert_application_record expertappl1_ on expert0_.id=expertappl1_.expert_id left outer join countries country2_ on expert0_.motherland=country2_.id where expertappl1_.latest=? order by convert(?) desc limit ?
2019-11-05 18:58:41.281 TRACE 15252 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BOOLEAN] - [true]
2019-11-05 18:58:41.281 TRACE 15252 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [null USING GBK]
2019-11-05 18:58:41.282  WARN 15252 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1064, SQLState: 42000
2019-11-05 18:58:41.282 ERROR 15252 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') desc limit 10' at line 5
2019-11-05 18:58:41.285 ERROR 15252 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') desc limit 10' at line 5
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:118) ~[mysql-connector-java-8.0.11.jar:8.0.11]
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95) ~[mysql-connector-java-8.0.11.jar:8.0.11]
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.11.jar:8.0.11]
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960) ~[mysql-connector-java-8.0.11.jar:8.0.11]
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1019) ~[mysql-connector-java-8.0.11.jar:8.0.11]
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-2.7.9.jar:na]

谢谢大家。

最佳答案

@formula 注解无法与 native 查询一起使用。 这是链接:I am the link.

我不太熟悉 jpa,但这里是比使用 @Formula 注释更好的解决方案。

首先您需要创建自定义方言 这是示例:

public class CustomMariaDB53Dialect extends MariaDB53Dialect {
    private static final Logger LOG = LoggerFactory.getLogger(CustomMariaDB53Dialect.class);

    public CustomMariaDB53Dialect() {
        super();
}

然后向Dialect注册一个函数 这是代码:

public class CustomMariaDB53Dialect extends MariaDB53Dialect {
    private static final Logger LOG = LoggerFactory.getLogger(CustomMariaDB53Dialect.class);

    public CustomMariaDB53Dialect() {
        super();
        registerFunction("convertEncode", new SQLFunctionTemplate(StandardBasicTypes.STRING, "convert(?1 using ?2)"));
    }
}

registerFunction 方法的第一个参数是函数名称。

第二个是SqlFunction的实现

?1?2 表示函数的参数 所以函数模板是 convert(?1 using ?2)

完成上述步骤后。

你应该告诉 hibernate 你正在使用新的方言

配置的路径是hibernate.dialect

示例如下:

hibernate.dialect=xxx.xxx.CustomMariaDB53Dialect 

如果您使用的是 spring boot jpa。

这是配置:

spring:
  jpa:
    hibernate:
    properties:
      hibernate:
        dialect: xxx.xxx.CustomMariaDB53Dialect

最后一步是在查询中使用该函数。

示例如下:

Expression<String> countryName = builder().function(
                        "convertEncode", 
                        String.class,
                        join.get(Country_.NAME),
                        builder().literal("gbk")
                );

                return direction.isDescending() ? builder().desc(countryName ) : builder().asc(countryName );

这是最终的sql:

order by convert(expert0_.name_zh using ?) asc limit ?

干杯!!!

关于java - 如何通过条件查询调用使用mysql关键字作为参数的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58709930/

相关文章:

java - 如何使用 for 语句在 java 数组中创建多个图像?

java - 远程处理案例中的惰性/急切加载策略 (JPA)

java - 在 JPA 查询上设置 ORDER BY 和 LIMIT 子句

jpa - 元组结果标准 API 子查询

java - 获取 java.lang.ClassCastException : java. lang.Integer 无法转换为 [Ljava.lang.Object 错误

java - 对两个条件查询使用相同的谓词

java - 用于调试目的的命名 (toString) Lambda 表达式

java - Android ViewGroup 删除 View ?

java - 在java中删除二维数组中的一些元素

java - DataNucleus 3.0.0 版本需要哪些依赖项?