HIBERNATE JBoss.org
 |  Register  | 
     
News 
About 
   Feature List 
   Road Map 
Documentation 
   Related Projects 
   External Documentation 
Download 
Forum & Mailinglists 
Support & Training 
JIRA Issue Tracking
Wiki Community Area


Hibernate Public Training Courses


Get Hibernate in Action eBook!


JavaWorld 2003 Finalist


Jolt Award 2004 Winner
      
Documentation > Community Area > Using JasperReports with Hibernate

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[i].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()<values.length,

            "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;

    }

}

      

coWiki