在 Hibernate 的自定义 FileMaker 方言中限制结果
Limiting results in a custom FileMaker dialect for Hibernate
我正在尝试使用 Spring JPA 2.0.9 和 Hibernate 5.3.5 访问 FileMaker 16 数据库,使用 the official JDBC driver and this dialect for Hibernate。
我对方言进行了修改,以支持限制 FileMaker 结果集,添加如下限制处理程序:
public class FileMakerDialect extends Dialect {
...
private static final LimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
public String processSql(String sql, RowSelection selection) {
String soff = " offset ? rows";
String slim = " fetch first ? rows only";
StringBuilder sb = (new StringBuilder(sql.length() + soff.length() + slim.length())).append(sql);
if (LimitHelper.hasFirstRow(selection)) {
sb.append(soff);
}
if (LimitHelper.hasMaxRows(selection)) {
sb.append(slim);
}
return sb.toString();
}
public boolean supportsLimit() {
return true;
}
};
public LimitHandler getLimitHandler() {
return LIMIT_HANDLER;
}
...
}
限制处理程序只是将 offset ? rows fetch first ? rows only
添加到 select 查询的末尾。
现在我有一个测试在尝试从 Spring JPA 存储库获取分页结果时失败:
com.filemaker.jdbc.FMSQLException: [FileMaker][FileMaker JDBC]
FQL0001/(1:338): There is an error in the syntax of the query. at
com.filemaker.jdbc.FM_API.prepare(Unknown Source) at
com.filemaker.jdbc.FM_API.prepareRS(Unknown Source) at
com.filemaker.jdbc.FM_API.prepareRS(Unknown Source) at
com.filemaker.jdbc1.CommonJ1Statement.(Unknown Source) at
com.filemaker.jdbc2.CommonJ2Statement.(Unknown Source) at
com.filemaker.jdbc3.CommonJ3Statement.(Unknown Source) at
com.filemaker.jdbc3.J3PreparedStatement.(Unknown Source) at
com.filemaker.jdbc3.J3Connection.prepareStatement(Unknown Source) at
com.filemaker.jdbc2.CommonJ2Connection.prepareStatement(Unknown
Source) at
com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:318)
at
com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
at
org.hibernate.engine.jdbc.internal.StatementPreparerImpl.doPrepare(StatementPreparerImpl.java:146)
at
org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 87 more
但是,如果我从 com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:318)
中取出看起来像 select * from "MarketingCategories" marketingc0_ offset ? rows fetch first ? rows only
的 SQL,将问号替换为数字并使用相同的驱动程序针对 FileMaker 数据库手动执行它,它成功 returns 个分页结果集。
我该如何处理这个异常?我希望获得如何进一步调试它的线索。没有 fm jdbc 驱动程序的源代码,反编译的 class 也没有行号信息,所以我无法在调试器中检查它。
在报告问题 here 时,我做了一个解决方法:
public class FileMakerDialect extends Dialect {
...
private static final LimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
public String processSql(String sql, RowSelection selection) {
String soff = String.format(" offset %d rows /*?*/", selection.getFirstRow());
String slim = String.format(" fetch first %d rows only /*?*/", selection.getMaxRows());
StringBuilder sb = (new StringBuilder(sql.length() + soff.length() + slim.length())).append(sql);
if (LimitHelper.hasFirstRow(selection)) {
sb.append(soff);
}
if (LimitHelper.hasMaxRows(selection)) {
sb.append(slim);
}
return sb.toString();
}
public boolean supportsLimit() {
return true;
}
};
...
}
它在注释中放置参数绑定的占位符,在限制处理程序中插入分页参数。
在此处查看我在 johnkeates FileMaker 方言上的补丁:https://github.com/fsans/FileMaker-Hibernate-dialect 以及一些其他改进。
我正在尝试使用 Spring JPA 2.0.9 和 Hibernate 5.3.5 访问 FileMaker 16 数据库,使用 the official JDBC driver and this dialect for Hibernate。
我对方言进行了修改,以支持限制 FileMaker 结果集,添加如下限制处理程序:
public class FileMakerDialect extends Dialect {
...
private static final LimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
public String processSql(String sql, RowSelection selection) {
String soff = " offset ? rows";
String slim = " fetch first ? rows only";
StringBuilder sb = (new StringBuilder(sql.length() + soff.length() + slim.length())).append(sql);
if (LimitHelper.hasFirstRow(selection)) {
sb.append(soff);
}
if (LimitHelper.hasMaxRows(selection)) {
sb.append(slim);
}
return sb.toString();
}
public boolean supportsLimit() {
return true;
}
};
public LimitHandler getLimitHandler() {
return LIMIT_HANDLER;
}
...
}
限制处理程序只是将 offset ? rows fetch first ? rows only
添加到 select 查询的末尾。
现在我有一个测试在尝试从 Spring JPA 存储库获取分页结果时失败:
com.filemaker.jdbc.FMSQLException: [FileMaker][FileMaker JDBC] FQL0001/(1:338): There is an error in the syntax of the query. at com.filemaker.jdbc.FM_API.prepare(Unknown Source) at com.filemaker.jdbc.FM_API.prepareRS(Unknown Source) at com.filemaker.jdbc.FM_API.prepareRS(Unknown Source) at com.filemaker.jdbc1.CommonJ1Statement.(Unknown Source) at com.filemaker.jdbc2.CommonJ2Statement.(Unknown Source) at com.filemaker.jdbc3.CommonJ3Statement.(Unknown Source) at com.filemaker.jdbc3.J3PreparedStatement.(Unknown Source) at com.filemaker.jdbc3.J3Connection.prepareStatement(Unknown Source) at com.filemaker.jdbc2.CommonJ2Connection.prepareStatement(Unknown Source) at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:318) at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.doPrepare(StatementPreparerImpl.java:146) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172) ... 87 more
但是,如果我从 com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:318)
中取出看起来像 select * from "MarketingCategories" marketingc0_ offset ? rows fetch first ? rows only
的 SQL,将问号替换为数字并使用相同的驱动程序针对 FileMaker 数据库手动执行它,它成功 returns 个分页结果集。
我该如何处理这个异常?我希望获得如何进一步调试它的线索。没有 fm jdbc 驱动程序的源代码,反编译的 class 也没有行号信息,所以我无法在调试器中检查它。
在报告问题 here 时,我做了一个解决方法:
public class FileMakerDialect extends Dialect {
...
private static final LimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
public String processSql(String sql, RowSelection selection) {
String soff = String.format(" offset %d rows /*?*/", selection.getFirstRow());
String slim = String.format(" fetch first %d rows only /*?*/", selection.getMaxRows());
StringBuilder sb = (new StringBuilder(sql.length() + soff.length() + slim.length())).append(sql);
if (LimitHelper.hasFirstRow(selection)) {
sb.append(soff);
}
if (LimitHelper.hasMaxRows(selection)) {
sb.append(slim);
}
return sb.toString();
}
public boolean supportsLimit() {
return true;
}
};
...
}
它在注释中放置参数绑定的占位符,在限制处理程序中插入分页参数。
在此处查看我在 johnkeates FileMaker 方言上的补丁:https://github.com/fsans/FileMaker-Hibernate-dialect 以及一些其他改进。