我有一个小型的Java服务连接到一个MySQL DB,用来存储文档。每个文档都有一个名称,当一个文档被复制时,新文档的名称为<previous name> (#)
。documents表如下所示:
| 身份证|名称|
| --------------|--------------|
| 1|A文件|
| 二|一份文件(1)|
| 三|第1102章一份文件(二)|
| 四|其他文件|
| 五|另一份文件(1)|
我有一个工作的MySQL查询,它选择了一个文档及其所有副本,我试图将其转换为jooq。
select * from documents
where name regexp '(TITLE_GOES_HERE|TITLE_GOES_HERE \\([:digit:]+\\))$';
-- For instance, to select rows 1, 2, and 3 of the above table,
-- I would replace `TITLE_GOES_HERE` with `A Document`, resulting
-- in the following MySQL query:
select * from documents
where name regexp '(A Document|A Document \\([:digit:]+\\))$';
**注意:**如果你想要一个可用的正则表达式测试器,你可以找到它here。它与MySQL版本略有不同,但足以用于演示目的。
为了让这个查询以编程方式工作,我必须用我想要查找的文档的名称替换正则表达式中的“TITLE_GOES_HERE”。然而,这在jooq中抛出了一个意想不到的错误。
public List<Document> getOriginalAndDuplicates(String docName) {
SelectQuery<DocumentRecord> select = getDSLContext().selectQuery(DOCUMENT);
select.addCondition(
DSL.condition(
DSL.field(
// Binding for both the document AND the name
// Notice that the name binding is inside the regular expression
"{0} regexp '({1} \\\\([:digit:]+\\\\))'",
Boolean.class,
DOCUMENT.NAME,
docName)));
Result<DocumentRecord> records = select.fetch();
List<Document> docs = records.stream().map(documentConverter::convertTo).toList();
return docs;
}
当我运行它时,我得到以下错误:
Caused by: org.jooq.exception.DataAccessException: SQL [select document.id, document.name from document where (document.name regexp '({1} \\([:digit:]+\\))')]; Syntax error in regular expression on line 1, character 2.
at org.jooq_3.14.16.MYSQL.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2903)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:757)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:389)
... 27 common frames omitted
Caused by: java.sql.SQLException: Syntax error in regular expression on line 1, character 2.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:555)
at com.mysql.cj.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:339)
at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:354)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
at org.jooq.tools.jdbc.DefaultPreparedStatement.execute(DefaultPreparedStatement.java:214)
at org.jooq.impl.Tools.executeStatementAndGetFirstResultSet(Tools.java:4217)
at org.jooq.impl.AbstractResultQuery.execute(AbstractResultQuery.java:283)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:375)
... 27 common frames omitted
发生错误的原因是第一个绑定({1}
)未被文档名称替换。
有人遇到过这样的事情吗?
**附加信息:**当我将{1}
替换为硬编码值时,例如A Document
,查询成功,没有任何问题。只有当我尝试将{1}
绑定到变量值时才会出现问题。
1条答案
按热度按时间abithluo1#
为什么你的普通SQL模板不起作用
jOOQ plain SQL template不会在字符串文字或注解以及其他内容中进行任何替换。根据文件:
解析规则
在处理这些普通SQL模板时,会运行一个迷你解析器,它处理以下内容
模板引擎会识别上述内容,并且在替换编号占位符和/或绑定变量时会忽略其中的内容。
你的模板应该这样写:
请注意,所需的
\\
数量取决于NO_BACKSLASH_ESCAPES
设置,您也可以在jOOQ中配置该设置。如果您没有使用普通的SQL模板,jOOQ会自动处理这个问题。改用jOOQ API
但为什么要使用模板呢?jOOQ使用
Field.likeRegex()
对该运算符提供了本机支持: