随笔 - 251  文章 - 504  trackbacks - 0
<2006年6月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

本博客系个人收集材料及学习记录之用,各类“大侠”勿扰!

留言簿(14)

随笔分类

收藏夹

My Favorite Web Sites

名Bloger

非著名Bloger

搜索

  •  

积分与排名

  • 积分 - 200393
  • 排名 - 285

最新评论

注: 此方法使用简单,但是没有分页读取数据,适合数据量不大情况下的报表

原文:
http://www.hibernate.org/79.html

Using JasperReports with Hibernate
This section will demonstrate a couple of ways to use the results of a Hibernate query as the datasource of a report in JasperReports.

When the Hibernate query returns a simple collection of objects, The JRBeanCollectionDataSource class in the JasperReports library will work fine.

--------------------------------------------------------------------------------------------------------
List cats = session.find("from eg.Cat");

Map parameters = new HashMap();
parameters.put("Title", "The Cat Report");

InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");
JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);
JasperReport jasperReport = JasperManager.compileReport(jasperDesign);

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(cats);
JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);

JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");

--------------------------------------------------------------------------------------------------------

  However, when the Hibernate query returns tuples of objects (each tuple as an array, each array as an element in the returned List), things get a little tricky. Jasper needs a way to reference each object in the array by a field name. This class is a good solution, but at this time you are required to pass an array of field names matching the results of the query.

--------------------------------------------------------------------------------------------------------
public class HibernateQueryResultDataSource implements JRDataSource {

private String[] fields;
private Iterator iterator;
private Object currentValue;

public HibernateQueryResultDataSource(List list, String[] fields) {
  this.fields = fields;
  this.iterator = list.iterator();
}

public Object getFieldValue(JRField field) throws JRException {
  Object value = null;
  int index = getFieldIndex(field.getName());
  if (index > -1) {
    Object[] values = (Object[])currentValue;
    value = values[index];
  }
  return value;
}

public boolean next() throws JRException {
  currentValue = iterator.hasNext() ? iterator.next() : null;
  return (currentValue != null);
}

private int getFieldIndex(String field) {
  int index = -1;
  for (int i = 0; i < fields.length; i++) {
    if (fields
.equals(field)) {
    index = i;
    break;
    }
  }
  return index;
}

}

--------------------------------------------------------------------------------------------------------

Now running your report would look something like this:


--------------------------------------------------------------------------------------------------------
List cats = session.find("select cat.type, cat.birthdate, cat.name from eg.DomesticCat cat");

Map parameters = new HashMap();
parameters.put("Title", "The Cat Report");

InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");
JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);
JasperReport jasperReport = JasperManager.compileReport(jasperDesign);

String[] fields = new String[] { "type", "birthdate", "name"};
HibernateQueryResultDataSource ds = new HibernateQueryResultDataSource(cats, fields);
JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);

JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");

--------------------------------------------------------------------------------------------------------


Another, alternate implementation, from Erik Romson:


--------------------------------------------------------------------------------------------------------
public class HibernateQueryResultDataSource implements JRDataSource
{
  private static final transient Logger logger =
    Logger.Factory.getInstance(HibernateQueryResultDataSource.class);
  protected HashMap fieldsToIdxMap=new HashMap();
  protected Iterator iterator;
  protected Object currentValue;
  List values;

  public HibernateQueryResultDataSource(List list, String query)
  {
    int start =query.indexOf("select ");
    int stop =query.indexOf(" from ");
    Assertion.assertTrue(
      (start!=-1) &&
      (stop!=-1),
      "The query "+
      query+
      " must be of the form select x,x from ..."
    );
    start+="select".length();
    String parameters=query.substring(start,stop);
    parameters=parameters.trim();
    Assertion.assertTrue(
        parameters.length()>0,
        "The query "+
        query+
        " seems to be weird"
    );
    StringTokenizer tokenizer=new StringTokenizer(parameters,",");
    int idx=0;
    while( tokenizer.hasMoreTokens() )
    {
        String parameter=tokenizer.nextToken();
        fieldsToIdxMap.put( parameter.trim(), new Integer(idx) );
        idx++;
    }
    values=list;
    this.iterator = list.iterator();
  }
public Object getFieldValue(JRField field) throws JRException
  {
    String fieldName=field.getName().replace('_','.');
    //JasperReports does not allow '.' in field names, so we
    //use '_' for nested properties instead and must convert here
    //(comment added by kbrown)
    Integer idxInt=(Integer) fieldsToIdxMap.get(fieldName);
    if (idxInt==null)
    {
        Assertion.fail(
          "The field \""+
          fieldName+
          "\" did not have an index mapping. Should be one off "+
          fieldsToIdxMap.keySet()
        );
    }
    Object[] values = (Object[]) currentValue;
    Assertion.assertTrue(
        idxInt.intValue()
        "The index from field "+
        fieldName+
        " was illegal"
    );
    Object value= values[ idxInt.intValue() ];
    if ( logger.isDebugEnabled() )
    {
        logger.debug("fetched value "+value+" from field "+fieldName);
    }
    return value;
  }

  public boolean next() throws JRException
  {
    currentValue = iterator.hasNext() ? iterator.next() : null;
    return currentValue != null;
  }

  public List getValues()
  {
    return values;
  }
}

--------------------------------------------------------------------------------------------------------

Using JasperReports with Hibernate
This section will demonstrate a couple of ways to use the results of a Hibernate query as the datasource of a report in JasperReports.

When the Hibernate query returns a simple collection of objects, The JRBeanCollectionDataSource class in the JasperReports library will work fine.

List cats = session.find("from eg.Cat");

Map parameters = new HashMap();
parameters.put("Title", "The Cat Report");

InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");
JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);
JasperReport jasperReport = JasperManager.compileReport(jasperDesign);

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(cats);
JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);

JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");
However, when the Hibernate query returns tuples of objects (each tuple as an array, each array as an element in the returned List), things get a little tricky. Jasper needs a way to reference each object in the array by a field name. This class is a good solution, but at this time you are required to pass an array of field names matching the results of the query.

public class HibernateQueryResultDataSource implements JRDataSource {

private String[] fields;
private Iterator iterator;
private Object currentValue;

public HibernateQueryResultDataSource(List list, String[] fields) {
  this.fields = fields;
  this.iterator = list.iterator();
}

public Object getFieldValue(JRField field) throws JRException {
  Object value = null;
  int index = getFieldIndex(field.getName());
  if (index > -1) {
    Object[] values = (Object[])currentValue;
    value = values[index];
  }
  return value;
}

public boolean next() throws JRException {
  currentValue = iterator.hasNext() ? iterator.next() : null;
  return (currentValue != null);
}

private int getFieldIndex(String field) {
  int index = -1;
  for (int i = 0; i < fields.length; i++) {
    if (fields
.equals(field)) {
    index = i;
    break;
    }
  }
  return index;
}

}
Now running your report would look something like this:

List cats = session.find("select cat.type, cat.birthdate, cat.name from eg.DomesticCat cat");

Map parameters = new HashMap();
parameters.put("Title", "The Cat Report");

InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");
JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);
JasperReport jasperReport = JasperManager.compileReport(jasperDesign);

String[] fields = new String[] { "type", "birthdate", "name"};
HibernateQueryResultDataSource ds = new HibernateQueryResultDataSource(cats, fields);
JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);

JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");

--------------------------------------------------------------------------------

Another, alternate implementation, from Erik Romson:

public class HibernateQueryResultDataSource implements JRDataSource
{
  private static final transient Logger logger =
    Logger.Factory.getInstance(HibernateQueryResultDataSource.class);
  protected HashMap fieldsToIdxMap=new HashMap();
  protected Iterator iterator;
  protected Object currentValue;
  List values;

  public HibernateQueryResultDataSource(List list, String query)
  {
    int start =query.indexOf("select ");
    int stop =query.indexOf(" from ");
    Assertion.assertTrue(
      (start!=-1) &&
      (stop!=-1),
      "The query "+
      query+
      " must be of the form select x,x from ..."
    );
    start+="select".length();
    String parameters=query.substring(start,stop);
    parameters=parameters.trim();
    Assertion.assertTrue(
        parameters.length()>0,
        "The query "+
        query+
        " seems to be weird"
    );
    StringTokenizer tokenizer=new StringTokenizer(parameters,",");
    int idx=0;
    while( tokenizer.hasMoreTokens() )
    {
        String parameter=tokenizer.nextToken();
        fieldsToIdxMap.put( parameter.trim(), new Integer(idx) );
        idx++;
    }
    values=list;
    this.iterator = list.iterator();
  }

  public Object getFieldValue(JRField field) throws JRException
  {
    String fieldName=field.getName().replace('_','.');
    //JasperReports does not allow '.' in field names, so we
    //use '_' for nested properties instead and must convert here
    //(comment added by kbrown)
    Integer idxInt=(Integer) fieldsToIdxMap.get(fieldName);
    if (idxInt==null)
    {
        Assertion.fail(
          "The field \""+
          fieldName+
          "\" did not have an index mapping. Should be one off "+
          fieldsToIdxMap.keySet()
        );
    }
    Object[] values = (Object[]) currentValue;
    Assertion.assertTrue(
        idxInt.intValue()
        "The index from field "+
        fieldName+
        " was illegal"
    );
    Object value= values[ idxInt.intValue() ];
    if ( logger.isDebugEnabled() )
    {
        logger.debug("fetched value "+value+" from field "+fieldName);
    }
    return value;
  }

  public boolean next() throws JRException
  {
    currentValue = iterator.hasNext() ? iterator.next() : null;
    return currentValue != null;
  }

  public List getValues()
  {
    return values;
  }
}

--------------------------------------------------------------------------------

Using the information from this page I've made a patch to JasperReports 0.6.5. You can find the patch at:
http://www.waltermourao.com.br/JasperReports/jr65_hql.zip or you can download the full version from: http://www.waltermourao.com.br/JasperReports/jasperreports-hql-0.6.5.zip

posted on 2006-06-29 19:58 matthew 阅读(1606) 评论(0)  编辑  收藏 所属分类: 报表设计与开发

只有注册用户登录后才能发表评论。


网站导航: