注: 此方法使用簡單,但是沒有分頁讀取數據,適合數據量不大情況下的報表
原文:
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 閱讀(1612)
評論(0) 編輯 收藏 所屬分類:
報表設計與開發