信息数据库的分页

问题描述 投票:1回答:1

我试图为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类编写自己的实现,并在加载Hibernate方言时加载它。但每次我启动我的应用程序时,它都会选择默认的方言而不是我的。

有一个问题在hibernate中打开了-。https:/hibernate.atlassian.net浏览HHH-5414。.

但我担心由于DB本身不支持,那么如果我尝试手动做这个,它会有多大的效率,因为这将是一个基于偏移的分页,我觉得这将是一个性能的打击,可能无法解决问题。

我想知道,考虑到这些情况,有什么办法可以最好地支持 informix 的分页。

hibernate pagination offset informix
1个回答
0
投票

是的,现在的Hibernate中已经解决了这个问题(至少在目前我们主要停留在jboss EAP7服务器上的5.3.10.Final-redhat-00001中),你只需要在Hibernate中添加你的

<property name="hibernate.dialect" value="org.hibernate.dialect.Informix10Dialect" />

到你的persistence.xml中,然后就可以正常工作了。通过 作品 我指的是行文中的代码

if (pageSize > 0) {
    int firstResult = pageNo * pageSize - pageSize;
    query.setFirstResult(firstResult);
    query.setMaxResults(pageSize);
}

其中query是一个javax.persistence.Query。

一个合理的期望是,发出这样的查询后,SQL的 "原生 "输出会是这样的形式。

select skip <firstResult> limit <pageSize> [rest of the select statement]

来发送至 informix。然而,Hibernate直到Hibernate 5才修复了这个问题。

也许这并不好看,但被卡在古老的JBOSS或其他可怕的老平台带来的古老hibernate版本所困,你能做的就是简单地自己修复代码。不久前,我们曾经黑掉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由

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

© www.soinside.com 2019 - 2024. All rights reserved.