JasperReports:如何在列表中将超过1000个值放入$ X()语句中

时间:2013-12-03 07:00:02

标签: java oracle hibernate jasper-reports

我正在处理网络应用程序中的pdf报告,其中我需要显示可包含1000多个列表的报告

我在 JasperReports iReport )中有一个主查询,看起来像这样

<queryString><![CDATA[select SITE_NAME, SITE_OWNER, SITE_CONTACT_NAME, SITE_PHONE, SITE_FAX, SITE_MAIL from **SAMPLE_VIEW** where $X{IN,site_id, siteIds} group by SITE_NAME, SITE_OWNER, SITE_CONTACT_NAME, SITE_PHONE, SITE_FAX, SITE_MAIL by SITE_NAME]]> </queryString>

其中$ X {IN,site_id,siteIds}

siteIds - 包含超过1000个值列表。

site_id - 列视图名称

所以我面临的问题是当siteIds包含超过1000个值时,我会得到以下错误

net.sf.jasperreports.engine.JRException: Error executing SQL statement for : report name
at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createDatasource(JRJdbcQueryExecuter.java:229)
at net.sf.jasperreports.engine.fill.JRFillDataset.createQueryDatasource(JRFillDataset.java:758)
at net.sf.jasperreports.engine.fill.JRFillDataset.initDatasource(JRFillDataset.java:623)
at net.sf.jasperreports.engine.fill.JRBaseFiller.setParameters(JRBaseFiller.java:1160)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:802)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:746)
at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:58)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:417)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:247)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)

Caused by: java.sql.SQLException: ORA-01795: maximum number of expressions in a list is 1000

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:573)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1891)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteDescribe(TTC7Protocol.java:830)
at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2391)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2672)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:589)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:527)
at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createDatasource(JRJdbcQueryExecuter.java:222)
... 102 more

信息 - PDF生成器耗时3667毫秒。

异常引起:java.sql.SQLException:ORA-01795:列表中的最大表达式数为1000

我已经使用

在Hibernate中解决了这个问题
private static final int PARAMETER_LIMIT = 999;

public static Criterion buildInCriterion(String propertyName, List<?> collection) {
    Criterion criterion = null;
    List<?> subList;
    int listSize = collection.size();
    for (int i = 0; i < listSize; i += PARAMETER_LIMIT) {
        if (listSize > i + PARAMETER_LIMIT) {
            subList = collection.subList(i, (i + PARAMETER_LIMIT));
        } else {
            subList = collection.subList(i, listSize);
        }
        if (criterion != null) {
            criterion = Restrictions.or(criterion, Restrictions.in(propertyName, subList));
        } else {
            criterion = Restrictions.in(propertyName, subList);
        }
    }
    return criterion;
}

我可以在 JasperReports 中为$ X语句使用任何解决方案吗?

1 个答案:

答案 0 :(得分:3)

您获得的错误消息不是特定于Jasper的,而是特定于Oracle的; Oracle在IN列表中不允许超过1000个元素。

如果不能让Jasper自动将IN列表拆分成几个子子句,您可以使用以下解决方法之一:

  • 将您的ID写入(临时)表格,并将$X{IN,site_id, siteIds}替换为WHERE site_id IN (SELECT site_id FROM <temporary_table_name> )
  • 使用您的ID集合并将$X(IN,site_id,siteIds}替换为WHERE site_id IN (SELECT site_id FROM TABLE(<bindvariable_with_collection_holding_siteIDs>)(这仅在Jasper支持集合作为绑定变量时才有效)