informix 数据库的分页
Posted
技术标签:
【中文标题】informix 数据库的分页【英文标题】:pagination for informix database 【发布时间】:2019-12-11 14:38:27 【问题描述】:我正在尝试为 IBM Informix db 进行分页,但 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/browse/HHH-5414。
该补丁不适用于我的本地。 但我担心,由于 DB 本身不支持,那么如果我尝试手动执行此操作会有多高效,因为这将是基于偏移量的分页,我认为这会影响性能并且可能无法解决问题。
我想知道在考虑这些情况下可以做些什么来最好地支持informix 的分页。
【问题讨论】:
我最近看到了这篇文章:-discourse.hibernate.org/t/…。它谈到 - “使用提供 Informix10LimitHandler 的 Informix10Dialect。” 【参考方案1】:是的,这个问题现在在 Hibernate 中得到了解决(至少在目前我们主要使用的 jboss EAP7 服务器附带的 5.3.10.Final-redhat-00001 中),你只需要添加你的
<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 或其他引入/需要古老休眠版本的可怕的旧平台中,您能做的就是简单地自己修复代码。不久前,我们曾经从
破解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,这当然是更好的选择!
【讨论】:
以上是关于informix 数据库的分页的主要内容,如果未能解决你的问题,请参考以下文章