我试图为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中已经解决了这个问题(至少在目前我们主要停留在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这是 当然是更好的选择!