Hibernate/JDBC 为 Informix 数据库生成错误的 SQL
Posted
技术标签:
【中文标题】Hibernate/JDBC 为 Informix 数据库生成错误的 SQL【英文标题】:Hibernate/JDBC generates wrong SQL for Informix database 【发布时间】:2013-10-07 07:53:22 【问题描述】:我正在尝试使用标准 JPA 方法在我们的 Spring 应用程序中实现分页。这是一个非常简化的示例:
TypedQuery<Department> depsQuery = em.createQuery("select d from Department d", Department.class);
depsQuery.setFirstResult(20);
depsQuery.setMaxResults(10);
depsQuery.getResultList();
此查询应在 Informix 中生成类似于 select skip 20 first 10
的内容。但是,它会生成:
select first 30 department0_.id as ... from DEPARTMENT department0_
我在 JBoss 的 standalone.xml
中有 <driver-class>com.informix.jdbc.IfxDriver</driver-class>
,在 persistence.xml
文件中有 <property name="hibernate.dialect" value="org.hibernate.dialect.InformixDialect" />
。如何让 Hibernate/JDBC 产生正确的查询?
【问题讨论】:
【参考方案1】:“org.hibernate.dialect.InformixDialect”不支持限制。这是课堂上的一个 sn-p:
public boolean supportsLimitOffset()
return false;
public String getLimitString(String querySelect, int offset, int limit)
if ( offset > 0 )
throw new UnsupportedOperationException( "query result offset is not supported" );
return new StringBuffer( querySelect.length() + 8 )
.append( querySelect )
.insert( querySelect.toLowerCase().indexOf( "select" ) + 6, " first " + limit )
.toString();
您可以扩展此类以创建自定义方言。然后覆盖以上两个方法。
public boolean supportsLimitOffset()
return true;
public String getLimitString(String querySelect, int offset, int limit)
return new StringBuffer( querySelect.length() + 8 )
.append( querySelect )
.insert( querySelect.toLowerCase().indexOf( "select" ) + 6," skip " + offset + " first " + limit).toString();
【讨论】:
我最终使用了InformixDialect,但这就是解决方案,谢谢。【参考方案2】:我遇到了同样的问题,上面的答案对我没有帮助。 仅覆盖 getLimitString 方法没有任何效果。 我也必须覆盖 LimitHandler 并打开一些布尔标志。
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.engine.spi.RowSelection;
public class TestDialect extends org.hibernate.dialect.InformixDialect
private static final LimitHandler LIMIT_HANDLER = new AbstractLimitHandler()
@Override
public String processSql(String sql, RowSelection selection)
return getMyLimitString(sql, selection.getFirstRow(), selection.getMaxRows());
@Override
public boolean supportsLimit()
return true;
@Override
public boolean bindLimitParametersFirst()
return true; // must do, otherwise there will be an exception cause of preparedStatments
;
//
////
//
public TestDialect()
super();
@Override
public LimitHandler getLimitHandler()
return LIMIT_HANDLER;
@Override
public String getLimitString(String querySelect, int offset, int limit)
return getMyLimitString(querySelect, offset, limit);
public static String getMyLimitString(String querySelect, int offset, int limit)
/* SQL Syntax:
* SELECT FIRST <limit> ...
* SELECT SKIP <offset> FIRST <limit> ...
*/
System.out.println("TestDialect.getMyLimitString()");
if (offset < 0 || limit < 0)
throw new IllegalArgumentException("Cannot perform limit query with negative limit and/or offset value(s)");
StringBuffer limitQuery = new StringBuffer(querySelect.length() + 10);
limitQuery.append(querySelect);
int indexOfEndOfSelect = querySelect.toLowerCase().indexOf("select") + 6;
if (offset == 0)
limitQuery.insert(indexOfEndOfSelect, " first ?" );
else
limitQuery.insert(indexOfEndOfSelect, " skip ?" + " first ?" );
return limitQuery.toString();
@Override
public boolean supportsLimit()
return true;
【讨论】:
以上是关于Hibernate/JDBC 为 Informix 数据库生成错误的 SQL的主要内容,如果未能解决你的问题,请参考以下文章
hibernate的速度问题--hibernate.jdbc.fetch_size和 hibernate.jdbc.batch_size
hibernate.jdbc.fetch_size和hibernate.jdbc.batch_size有什么区别?
hibernate.jdbc.fetch_size 的默认大小是多少?