informix 数据库的分页
pagination for informix database
我正在尝试为 IBM Informix 数据库进行分页,但是 Hibernate 方言有一些限制,因为它不会生成 LIMIT 查询。
当我查看 IBM Informix 手册时告诉我以下答案:-
"The Projection clause cannot include the SKIP, FIRST, or LIMIT keywords in these contexts:
when the SELECT statement is part of a view definition
in a subquery, except in the FROM clause of the outer query
in a cross-server distributed query in which a participating database server does not support the SKIP, FIRST, or LIMIT keywords."
我正在尝试为 LIMIT class 编写自己的实现并在加载 Hibernate 方言时加载它。但是每次我启动我的应用程序时,它都会选择默认方言而不是我的。
休眠中有一个未解决的问题 - https://hibernate.atlassian.net/browse/HHH-5414。
补丁在我的本地不起作用。
但我担心,由于数据库本身不支持,如果我尝试手动执行此操作,效率会有多高,因为那将是基于偏移的分页,我认为这会影响性能并且可能无法解决问题。
我想知道在考虑这些场景以支持 informix 分页的情况下,可以做些什么最好。
是的,现在在 Hibernate 中解决了这个问题(至少在 5.3.10.Final-redhat-00001 中是这样,目前 jboss EAP7 服务器是我们最常使用的服务器),你只需要添加你的
<property name="hibernate.dialect" value="org.hibernate.dialect.Informix10Dialect" />
到你的 persistence.xml 然后它工作正常。 works 我的意思是
行中的代码
if (pageSize > 0) {
int firstResult = pageNo * pageSize - pageSize;
query.setFirstResult(firstResult);
query.setMaxResults(pageSize);
}
其中查询是 javax.persistence.Query.
触发此类查询的合理期望是 SQL 'native' 表单上的输出
select skip <firstResult> limit <pageSize> [rest of the select statement]
将发送到 informix。但是,Hibernate 直到 Hibernate 5 才修复此问题。
也许它并不漂亮,但是如果你被困在古老的 JBOSS 或其他可怕的旧平台带来 in/requiring 古老的休眠版本中,你能做的就是简单地自己修复代码。不久前,我们曾经从
破解 hibernate-core
hibernate-core-4.x.x.Final
被黑
hibernate-core-4.x.x.Final-pagination
这只是替换 类
org.hibernate.dialect.InformixDialect
org.hibernate.dialect.pagination.NoopLimitHandler
org.hibernate.dialect.pagination.FirstLimitHandler
所以这些首先支持limitOffSet by
@Override
public boolean supportsLimitOffset() {
return true;
}
然后我们只是以一些简单的方式实现了这些东西,例如
public final class InformixDialect extends Dialect {
..
private static final String SKIP = " SKIP ";
private static final String FIRST = " FIRST ";
private static final String SELECT = "select";
private static final int SELECT_LEN = SELECT.length();
..
@Override
public String getLimitString(String querySelect, int offset, int limit) {
return new StringBuilder(querySelect.length() + 8)
.append(querySelect)
.insert(querySelect.toLowerCase().indexOf(SELECT) + SELECT_LEN, new StringBuilder(SKIP).append(offset).append(FIRST).append(limit).toString()).toString();
}
..
和(NoopLimitHandler完全一样)
public final class FirstLimitHandler extends AbstractLimitHandler {
..
private static final String SKIP = " SKIP ";
private static final String FIRST = " FIRST ";
private static final String EMPTY = "";
private static final String SELECT = "select";
private static final int SELECT_LEN = SELECT.length();
..
@Override
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
..
@Override
public String processSql(String sql, RowSelection selection) {
if (selection == null || selection.getFirstRow() == null) {
return sql;
}
boolean hasOffset = LimitHelper.hasFirstRow(selection);
int maxOrLimit = this.getMaxOrLimit(selection);
String sqlOffset = hasOffset? SKIP + selection.getFirstRow(): EMPTY;
String sqlLimit = maxOrLimit > 0 ? FIRST + this.getMaxOrLimit(selection): EMPTY;
String sqlOffsetLimit = sqlOffset + sqlLimit;
return new StringBuilder(sql.length() + 10).append(sql).insert(sql.toLowerCase(Locale.ROOT).indexOf(SELECT) + SELECT_LEN, sqlOffsetLimit).toString();
}
..
不用说,如果您可以使用Hibernate 5,这当然是更好的选择!
我正在尝试为 IBM Informix 数据库进行分页,但是 Hibernate 方言有一些限制,因为它不会生成 LIMIT 查询。 当我查看 IBM Informix 手册时告诉我以下答案:-
"The Projection clause cannot include the SKIP, FIRST, or LIMIT keywords in these contexts:
when the SELECT statement is part of a view definition
in a subquery, except in the FROM clause of the outer query
in a cross-server distributed query in which a participating database server does not support the SKIP, FIRST, or LIMIT keywords."
我正在尝试为 LIMIT class 编写自己的实现并在加载 Hibernate 方言时加载它。但是每次我启动我的应用程序时,它都会选择默认方言而不是我的。
休眠中有一个未解决的问题 - https://hibernate.atlassian.net/browse/HHH-5414。
补丁在我的本地不起作用。 但我担心,由于数据库本身不支持,如果我尝试手动执行此操作,效率会有多高,因为那将是基于偏移的分页,我认为这会影响性能并且可能无法解决问题。
我想知道在考虑这些场景以支持 informix 分页的情况下,可以做些什么最好。
是的,现在在 Hibernate 中解决了这个问题(至少在 5.3.10.Final-redhat-00001 中是这样,目前 jboss EAP7 服务器是我们最常使用的服务器),你只需要添加你的
<property name="hibernate.dialect" value="org.hibernate.dialect.Informix10Dialect" />
到你的 persistence.xml 然后它工作正常。 works 我的意思是
行中的代码if (pageSize > 0) {
int firstResult = pageNo * pageSize - pageSize;
query.setFirstResult(firstResult);
query.setMaxResults(pageSize);
}
其中查询是 javax.persistence.Query.
触发此类查询的合理期望是 SQL 'native' 表单上的输出
select skip <firstResult> limit <pageSize> [rest of the select statement]
将发送到 informix。但是,Hibernate 直到 Hibernate 5 才修复此问题。
也许它并不漂亮,但是如果你被困在古老的 JBOSS 或其他可怕的旧平台带来 in/requiring 古老的休眠版本中,你能做的就是简单地自己修复代码。不久前,我们曾经从
破解 hibernate-corehibernate-core-4.x.x.Final
被黑
hibernate-core-4.x.x.Final-pagination
这只是替换 类
org.hibernate.dialect.InformixDialect
org.hibernate.dialect.pagination.NoopLimitHandler
org.hibernate.dialect.pagination.FirstLimitHandler
所以这些首先支持limitOffSet by
@Override
public boolean supportsLimitOffset() {
return true;
}
然后我们只是以一些简单的方式实现了这些东西,例如
public final class InformixDialect extends Dialect {
..
private static final String SKIP = " SKIP ";
private static final String FIRST = " FIRST ";
private static final String SELECT = "select";
private static final int SELECT_LEN = SELECT.length();
..
@Override
public String getLimitString(String querySelect, int offset, int limit) {
return new StringBuilder(querySelect.length() + 8)
.append(querySelect)
.insert(querySelect.toLowerCase().indexOf(SELECT) + SELECT_LEN, new StringBuilder(SKIP).append(offset).append(FIRST).append(limit).toString()).toString();
}
..
和(NoopLimitHandler完全一样)
public final class FirstLimitHandler extends AbstractLimitHandler {
..
private static final String SKIP = " SKIP ";
private static final String FIRST = " FIRST ";
private static final String EMPTY = "";
private static final String SELECT = "select";
private static final int SELECT_LEN = SELECT.length();
..
@Override
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
@Override
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) {
return 0;
}
..
@Override
public String processSql(String sql, RowSelection selection) {
if (selection == null || selection.getFirstRow() == null) {
return sql;
}
boolean hasOffset = LimitHelper.hasFirstRow(selection);
int maxOrLimit = this.getMaxOrLimit(selection);
String sqlOffset = hasOffset? SKIP + selection.getFirstRow(): EMPTY;
String sqlLimit = maxOrLimit > 0 ? FIRST + this.getMaxOrLimit(selection): EMPTY;
String sqlOffsetLimit = sqlOffset + sqlLimit;
return new StringBuilder(sql.length() + 10).append(sql).insert(sql.toLowerCase(Locale.ROOT).indexOf(SELECT) + SELECT_LEN, sqlOffsetLimit).toString();
}
..
不用说,如果您可以使用Hibernate 5,这当然是更好的选择!