如何通过条件查询调用使用 mysql 关键字作为参数的函数?
how to call the function that was using mysql keywords as parameters by the criteria query?
我正在使用 mysql 和 jpa 规范查询。
我想知道如何调用使用 mysql 关键字作为参数的函数。
示例如下:
select * from schema3.countries order by convert(name using GBK);
convert
方法使用 using
和 GBK
关键字作为参数。
我想通过条件查询调用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]
谢谢大家
我将 sql 更改为以下内容:
select *, convert(name using GBK) as nameGBK from schema3.countries order by nameGBK;
所以下一个问题是如何将计算列添加到选择中。
我们可以在国家模型中添加一列。
字段名称为nameGBK
并使用@Formula注解;
这是代码
@Column(nullable = false, unique = true)
private String name;
@Formula("convert(name using GBK)")
private String nameGBK;
然后在条件查询中我们可以按 nameGBK
排序。
这是代码:
builder.desc(join.get(Country_.NAME_GBK));
但是我使用的jpa无法解析关键字using
和GBK
所以我们必须扩展
您正在使用的方言并注册关键字。
代码如下:
public class CustomMariaDB53Dialect extends MariaDB53Dialect {
private static final Logger LOG = LoggerFactory.getLogger(CustomMariaDB53Dialect.class);
public CustomMariaDB53Dialect() {
super();
registerKeyword("using");
registerKeyword("USING");
registerKeyword("GBK");
registerKeyword("gbk");
}
}
并更改配置以告知休眠程序您正在使用新的方言。
如果您使用的是 spring 数据 jpa。
然后是配置:
spring:
h2:
console:
enabled: true
datasource:
url: jdbc:mysql://dev:13306/schema3?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&zeroDateTimeBehavior=CONVERT_TO_NULL&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
initialization-mode: always
liquibase:
enabled: false
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
order_inserts: true
#here to tell the hibernate you are using a new dialect.
dialect: com.hide.hide.CustomMariaDB53Dialect
jdbc:
batch_size: 100
如果对您有帮助,请给我投票。谢谢。
@formula
注释不能用于本机查询。
这是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.dialect
示例如下:
hibernate.dialect=xxx.xxx.CustomMariaDB53Dialect
如果您正在使用 spring 启动 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 ?
干杯!!!
我正在使用 mysql 和 jpa 规范查询。 我想知道如何调用使用 mysql 关键字作为参数的函数。
示例如下:
select * from schema3.countries order by convert(name using GBK);
convert
方法使用 using
和 GBK
关键字作为参数。
我想通过条件查询调用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]
谢谢大家
我将 sql 更改为以下内容:
select *, convert(name using GBK) as nameGBK from schema3.countries order by nameGBK;
所以下一个问题是如何将计算列添加到选择中。
我们可以在国家模型中添加一列。
字段名称为nameGBK
并使用@Formula注解;
这是代码
@Column(nullable = false, unique = true)
private String name;
@Formula("convert(name using GBK)")
private String nameGBK;
然后在条件查询中我们可以按 nameGBK
排序。
这是代码:
builder.desc(join.get(Country_.NAME_GBK));
但是我使用的jpa无法解析关键字using
和GBK
所以我们必须扩展
您正在使用的方言并注册关键字。
代码如下:
public class CustomMariaDB53Dialect extends MariaDB53Dialect {
private static final Logger LOG = LoggerFactory.getLogger(CustomMariaDB53Dialect.class);
public CustomMariaDB53Dialect() {
super();
registerKeyword("using");
registerKeyword("USING");
registerKeyword("GBK");
registerKeyword("gbk");
}
}
并更改配置以告知休眠程序您正在使用新的方言。 如果您使用的是 spring 数据 jpa。 然后是配置:
spring:
h2:
console:
enabled: true
datasource:
url: jdbc:mysql://dev:13306/schema3?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&zeroDateTimeBehavior=CONVERT_TO_NULL&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
initialization-mode: always
liquibase:
enabled: false
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
order_inserts: true
#here to tell the hibernate you are using a new dialect.
dialect: com.hide.hide.CustomMariaDB53Dialect
jdbc:
batch_size: 100
如果对您有帮助,请给我投票。谢谢。
@formula
注释不能用于本机查询。
这是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.dialect
示例如下:
hibernate.dialect=xxx.xxx.CustomMariaDB53Dialect
如果您正在使用 spring 启动 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 ?
干杯!!!