网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > JAVA > 新手入门 > 开发工具 > 使用JasperReport与iBATIS开发Web报表  

使用JasperReport与iBATIS开发Web报表

2008-01-24  作者:bitsCN整理  来源:中国网管联盟  点评 投稿 收藏

 三、        处理iBati返回数据 网管网www_bitscn_com

  如果iBATIS没有采用JavaBean作为返回对象,则可以采用java.util.map作为数据的返回对象。采用java.util.Map对象,需要额外的一些步骤。下面的代码则说明了iBATIS的select语句返回的java.util.Map对象。Src/ iBATIS.xml:
  网管网www_bitscn_com

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN" "http://iBATIS.apache.org/dtd/sql-map-2.dtd"> <sqlMap> <select id="salesByListOfMapsSQL" resultClass="java.util.HashMap"> SELECT E.EMPLOYEE_ID "ID", E.FIRST_NAME "FIRST", E.LAST_NAME "LAST", MS.TOTAL_SALES "TOTAL", MS.LATEST_SALE FROM EMPLOYEE E, MONTHLY_SALES MS WHERE E.EMPLOYEE_ID = MS.EMPLOYEE_ID AND MS.MONTH = #value# </select> <resultMap id="searchResultList" class="MonthlySalesBean"> <result property="employeeID" column="ID"/> <result property="first" column="FIRST"/> <result property="last" column="LAST"/> <result property="total" column="TOTAL"/> <result property="latestSale.amount" column="LATEST_SALE"/> </resultMap> <select id="salesByJavaBeansSQL" resultMap="searchResultList"> SELECT E.EMPLOYEE_ID "ID", E.FIRST_NAME "FIRST", E.LAST_NAME "LAST", MS.TOTAL_SALES "TOTAL", MS.LATEST_SALE FROM EMPLOYEE E, MONTHLY_SALES MS WHERE E.EMPLOYEE_ID = MS.EMPLOYEE_ID AND MS.MONTH = #value# </select> </sqlMap>
网管下载dl.bitscn.com

    上面的代码返回的对象即为map对象。请注意,map对象中的Key值直接来自于select语句,因此,像TO_CHAR(MS.TOTAL_SALES)这样的表达式在报表中不提倡使用。因此,比较人性化的为字段命名,是一件很值得的事情。因为map的key值是作为java.lang.Object类型来进行存储的,因此有必要对字段返回类型进行一下整理。

网管联盟bitsCN@com

    真正的数据填充类应该是ServiceLocatorBean.java类,其代码如下所示: 网管u家u.bitsCN.com

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletContext;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class ServiceLocatorBean implements ServiceLocatorIF {
private static final long serialVersionUID = -7166271873610635886L;
//the Spring application context
    private ApplicationContext appContext;
DAO dao = null;
public ServiceLocatorBean() {
try {
// get the spring context
            ServletContext context = FacesUtils.getServletContext();
this.appContext = WebApplicationContextUtils.
getRequiredWebApplicationContext(context); // create instance of the business object this.dao = (DAO) this.lookupService("dao"); Connection conn = this.dao.getSqlMapClient().getDataSource().getConnection(); conn.setAutoCommit(false); /* Creating a statement lets us issue commands against the connection. */ Statement s = conn.createStatement(); // just in case old tables from prior run (after first run which // will create the USER1 schema) try { s.execute("drop table employee"); s.execute("drop table monthly_sales"); } catch (Exception ex) { // not to be concerned (at least in this example } /* We create a table, add a few rows, and update one. */ s.execute("create table employee (employee_id int,
网管联盟bitsCN@com

first_name varchar(40), last_name varchar(40))"); s.execute("insert into employee values (1,'sterning', 'chen')"); s.execute("insert into employee values (2,'yuxuan', 'Wand')"); s.execute("insert into employee values (3,'Mickey', 'Li')"); s.execute("create table monthly_sales (employee_id int, total_sales numeric(16,
2), latest_sale numeric(8, 2), month int)"); s.execute("insert into monthly_sales values (1, 1600.50, 32.50, 1)"); s.execute("insert into monthly_sales values (2, 1544.20, 12.50, 1)"); s.execute("insert into monthly_sales values (3, 18814.80, 78.65, 1)"); s.execute("insert into monthly_sales values (1, 1450.50, 10.65, 2)"); s.execute("insert into monthly_sales values (2, 2004.25, 52.10, 2)"); s.execute("insert into monthly_sales values (3, 9819.00, 40.65, 2)"); s.close(); conn.commit(); } catch (SQLException sqle) { // just means the tables already exist sqle.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } } public DAO getDao() { return this.dao; } public Object lookupService(String serviceBeanName) { return appContext.getBean(serviceBeanName); } } 网管网www_bitscn_com
网管网www.bitscn.com

网管联盟bitsCN@com

网管网www_bitscn_com

    四、        将iBATIS数据填入JasperReport中
  
  就通常而言,采用Java Bean作为iBATIS的返回对象,相比起java.util.Map对象来说,更加的方便与可行。很多的开发人员采用iBATIS的这种方式来进行数据的映射,同时,此方法还可以无缝的将iBATIS与JapserReport集成起来。
  
  在JasperReport中,提供了一个JRDataSource的实现,从而开发人员可以通过此类来传递iBATIS的list对象给JasperReport模板。而JRBeanCollectionDataSource类使用JavaBean来构造,从而可以通过循环查找collection并获得相应的bean属性。如下的代码示例说明了如何在调用JasperReport引擎时实例化JRBeanCollectionDataSource对象。

网管下载dl.bitscn.com

网管联盟bitsCN_com

import java.io.File; import java.util.HashMap; import java.util.List; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import net.sf.jasperreports.engine.util.JRLoader; public class SearchBean { private final static String JAVA_BEAN_REPORT = "monthly_sales_java_beans.jasper"; private final static String LIST_OF_MAP_REPORT = "monthly_sales_list_of_maps.jasper"; public String generateFromJavaBeans () { try { ServiceLocatorIF sl = (ServiceLocatorIF) FacesUtils .getManagedBean("serviceLocatorBean"); List list = sl.getDao().getSqlMapClient().queryForList("salesByJavaBeansSQL", month); FacesUtils.setSessionAttribute("JASPER_PRINT", generateReport (list, JAVA_BEAN_REPORT)); viewReport = "true"; } catch (Exception ex) { ex.printStackTrace(); } return null; } public String generateFromListOfMaps () { try { ServiceLocatorIF sl = (ServiceLocatorIF) FacesUtils .getManagedBean("serviceLocatorBean"); List list = sl.getDao().getSqlMapClient().queryForList("salesByListOfMapsSQL", month); FacesUtils.setSessionAttribute("JASPER_PRINT", generateReport (list, LIST_OF_MAP_REPORT)); viewReport = "true"; } catch (Exception ex) { ex.printStackTrace(); } return null; } private JasperPrint generateReport (List dataList, String reportName) { JasperPrint jasperPrint = null; try { String localPath = FacesUtils.getServletContext().getRealPath("/"); File reportFile = new File(localPath + "WEB-INF" + File.separator + reportName); if (!reportFile.exists()) throw new JRRuntimeException(".jasper file not found. The report design must be compiled first."); JasperReport jasperReport = (JasperReport)JRLoader.loadObject(reportFile.getPath()); if (reportName.equals(JAVA_BEAN_REPORT)) { jasperPrint = JasperFillManager.fillReport( jasperReport, new HashMap(), new JRBeanCollectionDataSource (dataList)); } else { jasperPrint = JasperFillManager.fillReport( jasperReport, new HashMap(), new CustomJRDS (dataList)); } } catch (Exception ex) { ex.printStackTrace(); } return jasperPrint; } public String getMonth() { return month; } public void setMonth(String month) { this.month = month; } public String getViewReport() { return viewReport; } public void setViewReport(String viewReport) { this.viewReport = viewReport; } private String month = null; private String viewReport = null; }
中国网管联盟bitsCN.com

网管u家u.bitscn@com

 

    在上面的代码中,定义的参数map,是在运行时传递相关的参数值给JasperReport。例如,可以在报表模板中定义一个名为REPORT_TITLE的参数,然后在运行时传递这一参数的值给它,传递的方式一般是健/值对的形式。例如Key=REPORT_TITLE,Value=Sale Report。当然,参数是传递给fillReport方法。然后,JasperReport会加载已经编译好的Jasper模板文件(.jasper)。最后调用静态的fillReport方法。

网管论坛bbs_bitsCN_com

    而JasperPrint对象是在数据展示或显示时需要用到的。而在本例中,采用了JRPdfExporter来作为输出的格式,即输出为PDF格式文件,请参考PdfServlet.java文件,代码如下所示:

网管联盟bitsCN_com

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExporterParameter; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.export.JRPdfExporter; public class PdfServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { JasperPrint jasperPrint = (JasperPrint) request.getSession() .getAttribute("JASPER_PRINT"); List jasperPrintList = new ArrayList(); jasperPrintList.add(jasperPrint); JRPdfExporter exporter = new JRPdfExporter(); exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, jasperPrintList); ByteArrayOutputStream baos = new ByteArrayOutputStream(); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos); try { exporter.exportReport(); } catch (JRException e) { throw new ServletException(e); } byte[] bytes = baos.toByteArray(); if (bytes != null && bytes.length > 0) { response.setContentType("application/pdf"); response.setContentLength(bytes.length); ServletOutputStream ouputStream = response.getOutputStream(); try { ouputStream.write(bytes, 0, bytes.length); ouputStream.flush(); } finally { if (ouputStream != null) { try { ouputStream.close(); } catch (IOException ex) { } } } } } }
网管联盟bitsCN@com

    
    尽管上面的JasperReport机制可以将iBATIS连接起来,但应该根据项目报表的需要对JavaBean进行修改与调整。而JasperReport字段对象可以很好的与普通的JDBC字段进行匹配。例如,JasperReport将Oracle的numeric字段类型对应的转成java.math.BigDecimal对象类型。而在iBATIS的Bean属性应该与JasperReport中定义的字段类型进行很好的匹配。需要对字段的类型进行认真仔细的选择,因为不同类型或是不同表达式对数据的展示有不同的效果。例如,BigDecimal类型比String类型更加适合货币格式。 中国网管联盟bitsCN.com

网管论坛bbs_bitsCN_com


TAGs
 上一篇:四种流行的持久化框架比较   下一篇:使用java开发facebook网站应用程序
使用JasperReport与iBATIS开发Web报表 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
最新推荐文章:
网管论坛交流: