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,这当然是更好的选择