<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 310, comments - 6939, trackbacks - 0, articles - 3
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    使用JasperReport與iBATIS開發Web報表

    Posted on 2008-01-25 09:32 詩特林 閱讀(7004) 評論(10)  編輯  收藏 所屬分類: BI
    應該IT168寫的專稿:http://publish.itpub.net/j/2008-01-24/200801241020641.shtml
     

    使用JasperReportiBATIS開發Web報表

     

    JasperReport是一種采用純Java實現的快速且非常流行的生成報表的類庫。而對于任何的報表方案,取得數據并傳遞給報表引擎是其中最重要且最值得關心的方面。但遺憾的是,在這方面JasperReport本身似乎有一定的不足。而如今的很多Java應用程序,采用數據獲取框架來進行數據的匹配與動態生成SQL。例如iBATIS數據映射框架。當然,如果只是使用JasperReport獲取數據及管理數據的默認機制的話,不足以與現成的數據框架進行很好的平衡。但可喜的是,可以通過使用傳遞給JasperReport一個數據庫的連接進行代替,當然這種連接可以通過使用XML進行非常方便的管理與配置。

    源代碼下載:http://cid-7b377ace522ff6c7.skydrive.live.com/self.aspx/iBatisJasper/iBatisJasper.rar

    一、準備工作

    Hibernate類似,iBATIS也是一個ORM解決方案,不同的是兩者各有側重。Hibernate提供了Java對象到數據庫表之間的直接映射,開發者無需直接涉及數據庫操作的實現細節,實現了一站式的ORM解決方案。而iBATIS則采取了另一種方式,即提供Java對象到SQL(面向參數和結果集)的映射實現,實際的數據庫操作需要通過手動編寫SQL實現。

    iBATIS是又一個O/R Mapping解決方案,j2eeO/R方案真是多,和Hibernate相比,iBATIS最大的特點就是小巧,上手很快。如果你不需要太多復雜的功能,iBATIS是能滿足你的要求又足夠靈活的最簡單的解決方案。在本文的示例中,采用Spring+JSF+iBATIS的模式進行示例的開發。所使用的lib如下圖所示:


    1.所使用的jar

    二、在iReport中可視化定制模板

    定制報表格式有二種方式,一種就是寫jrxml文件,其實就是xml文件,只不過是后綴名不一樣罷了。另一種方式更直接,就是生成一個JasperDesign類的實例,在japsperDesign中自己定義模板。jrxml文件也是通過一個JRXmlLoad加載過來,轉成JasperDesign類的實例。也就是說寫jrxml文件還需要進行解析,加載。現實中我們使用的報表一般格式比較固定,因而可以通過先使用iReport工具生成模板,再加載解析的方式。這種方式簡單,而且可見性強。

    iReport做為一個優秀的報表設計器,有著功能非常強大的特性。作為開源的Java程序,不但有適合于Windows安裝的應用程序,同時,還提供完全開放的源代碼,可供參考及原理分析。在本文中,主要通過圖形界面中的模板設計,以及與數據庫的連接等一系列的操作,來介紹如何定制一定要求的報表模板。

    通過iReport可初見化的圖形界面,可以設計出各種各樣的簡單或復雜的報表。通過iReport的這種可視化界面設計,可以為JasperReport提供優秀的報表模板,而無須去理解或是掌握那些復雜的XML語法。如此則可以Web報表開發節省大量的開發時間。

    在進行iReport模板設計之前,需要編寫JavaBean類:MonthlySalesBean.java,代碼如下:

    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.List;


    public class MonthlySalesBean {

        
    private int employeeID;;
        
    private String last = null;
        
    private String first = null;
        
    private BigDecimal total = null;
        
    private List sales = null;
        
    private LatestSale latestSale = null;
        
        
    public static List createBeanCollection () {
            List list 
    = new ArrayList ();
            
            MonthlySalesBean msb 
    = new MonthlySalesBean ();
            msb.setEmployeeID(
    1);
            msb.setFirst(
    "John");
            msb.setLast(
    "Doe");
            msb.setTotal(
    new BigDecimal ("1600.50"));
            
            LatestSale ls 
    = new LatestSale ();
            ls.setAmount(
    new BigDecimal ("32.21"));
            msb.setLatestSale(ls);
            
            list.add(msb);
            
            
    return list;
        }

        
    public int getEmployeeID() {
            
    return employeeID;
        }

        
    public void setEmployeeID(int employeeID) {
            
    this.employeeID = employeeID;
        }

        
    public String getFirst() {
            
    return first;
        }

        
    public void setFirst(String first) {
            
    this.first = first;
        }

        
    public String getLast() {
            
    return last;
        }

        
    public void setLast(String last) {
            
    this.last = last;
        }

        
    public BigDecimal getTotal() {
            
    return total;
        }

        
    public void setTotal(BigDecimal total) {
            
    this.total = total;
        }

        
    public List getSales() {
            
    return sales;
        }

        
    public void setSales(List sales) {
            
    this.sales = sales;
        }

        
    public LatestSale getLatestSale() {
            
    return latestSale;
        }

        
    public void setLatestSale(LatestSale latestSale) {
            
    this.latestSale = latestSale;
        }
        
    }


     

    將上面的類打成一個jar包,并置于classpath目錄下,則iReport可以進行訪問。使用JavaBean做為數據源,為了在設計報表時能夠看到數據,在程序中要為iReport提供一個靜態方法,該方法返回上面定義JavaBean的一個結果集,這個靜態方法可能在程序運行中并不是必須的,但是在iReport中它確實必須的,換句話說,這個靜態方法是專門為iReport量身定做的,為了iReport在設計報表時能夠調用這個靜態方法返回相應的JavaBean結果集,以便設計的報表放在Java項目中之前就能像使用SQL數據庫數據源一樣可以瀏覽。在iReport中先進行數據源的連接配置,此處采用是JavaBeans set data source連接方式:

    2.iReport進行數據源的連接

     

    三、處理iBati返回數據

     

    如果iBATIS沒有采用JavaBean作為返回對象,則可以采用java.util.map作為數據的返回對象。采用java.util.Map對象,需要額外的一些步驟。下面的代碼則說明了iBATISselect語句返回的java.util.Map對象。Src/ iBATIS.xml

    <?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>

     

    上面的代碼返回的對象即為map對象。請注意,map對象中的Key值直接來自于select語句,因此,像TO_CHARMS.TOTAL_SALES)這樣的表達式在報表中不提倡使用。因此,比較人性化的為字段命名,是一件很值得的事情。因為mapkey值是作為java.lang.Object類型來進行存儲的,因此有必要對字段返回類型進行一下整理。

    真正的數據填充類應該是ServiceLocatorBean.java類,其代碼如下所示:

    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, 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);
        }


    }


     

    四、將iBATIS數據填入JasperReport

    就通常而言,采用Java Bean作為iBATIS的返回對象,相比起java.util.Map對象來說,更加的方便與可行。很多的開發人員采用iBATIS的這種方式來進行數據的映射,同時,此方法還可以無縫的將iBATISJapserReport集成起來。

    JasperReport中,提供了一個JRDataSource的實現,從而開發人員可以通過此類來傳遞iBATISlist對象給JasperReport模板。而JRBeanCollectionDataSource類使用JavaBean來構造,從而可以通過循環查找collection并獲得相應的bean屬性。如下的代碼示例說明了如何在調用JasperReport引擎時實例化JRBeanCollectionDataSource對象。

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


     

    在上面的代碼中,定義的參數map,是在運行時傳遞相關的參數值給JasperReport。例如,可以在報表模板中定義一個名為REPORT_TITLE的參數,然后在運行時傳遞這一參數的值給它,傳遞的方式一般是健/值對的形式。例如Key=REPORT_TITLEValue=Sale Report。當然,參數是傳遞給fillReport方法。然后,JasperReport會加載已經編譯好的Jasper模板文件(.jasper)。最后調用靜態的fillReport方法。

    JasperPrint對象是在數據展示或顯示時需要用到的。而在本例中,采用了JRPdfExporter來作為輸出的格式,即輸出為PDF格式文件,請參考PdfServlet.java文件,代碼如下所示:

    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) {
                        }

                    }

                }

            }

        }

    }


     

    盡管上面的JasperReport機制可以將iBATIS連接起來,但應該根據項目報表的需要對JavaBean進行修改與調整。而JasperReport字段對象可以很好的與普通的JDBC字段進行匹配。例如,JasperReportOraclenumeric字段類型對應的轉成java.math.BigDecimal對象類型。而在iBATISBean屬性應該與JasperReport中定義的字段類型進行很好的匹配。需要對字段的類型進行認真仔細的選擇,因為不同類型或是不同表達式對數據的展示有不同的效果。例如,BigDecimal類型比String類型更加適合貨幣格式。

    五、代碼運行效果

    1.系統主界面

     


    3.報表運行主界面

    2.采用JavaBean生成報表


    4.采用JavaBean生成報表

    六、小結

    在本文中,筆者展示了如何使用比較成熟的iBATIS數據框架來對JasperReport進行數據填充。iBATIS最大的特點是簡單,而iBATIS所擁有的易維護及易配置特性,在JasperReport中充分的體現出來了。這種簡單與靈活性,正好彌補了JasperReport在這方面的不足,從而達到靈活開發Web報表的目的。



    評論

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-01-25 11:26 by ci
    不錯....

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-01-25 14:55 by cnfox
    rar文件被破壞?

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-01-26 19:48 by julycoolboy
    大概看了一下,博主做的不錯,我來談談我使用JR的心得,JR本身分為推和拉的方式來填充模板,使用BEAN做為數據源,就是先取出數據后推到JR中去,我這里返回的是一個自定義Iterator,里面使用的ResultSet,這個好處就是不會一次性把數據取出來,生成報表的時候會一條條取,這樣就能突破推方式的數據量極限了(正常方式下,一個萬條數據的LIST,我們的開發PC都容易內存溢出)

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-04-30 16:38 by regale
    不錯....

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-07-02 17:14 by wanxinge
    發一份給我可以嗎?萬分感謝啊,下載rar被破壞。我的郵箱:wangxinge_5689@163.com

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-12-05 11:52 by ireport
    發份我,不勝感激!
    lujuju@qq.com

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2008-12-26 04:09 by renbao
    我也需要,謝謝22624223@qq.com

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2009-10-07 03:00 by Wonner
    千萬不要用iBATIS.

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2014-11-26 16:10 by 阿浪
    正在學習這個,想參考一下,能發一份給我嗎?
    1572669095@qq.com

    # re: 使用JasperReport與iBATIS開發Web報表  回復  更多評論   

    2015-01-16 16:42 by hanck
    學習中,望前輩們多多指導啊,可以發一份給我嗎?不勝感激!
    389610110@qq.com
    主站蜘蛛池模板: 久久免费视频网站| 亚洲综合色成在线播放| 美女隐私免费视频看| 亚洲小说区图片区另类春色| 久久国产乱子伦精品免费看| 亚洲色精品三区二区一区| 亚洲人成网亚洲欧洲无码久久| 免费国产作爱视频网站| WWW国产成人免费观看视频| 亚洲春色另类小说| 美腿丝袜亚洲综合| 国产在线国偷精品产拍免费| 精品国产免费一区二区三区| 中文字幕乱码亚洲无线三区| 亚洲伊人久久大香线蕉综合图片 | 成年人免费观看视频网站| 一级毛片视频免费| 国产日本亚洲一区二区三区 | 亚洲av第一网站久章草| 亚洲AV成人精品网站在线播放| 国产真人无遮挡作爱免费视频| 日韩精品无码专区免费播放| 校园亚洲春色另类小说合集| 亚洲国产成人精品无码区在线秒播 | 久久WWW色情成人免费观看| 插鸡网站在线播放免费观看| 亚洲人av高清无码| 亚洲精品动漫在线| 亚洲中文字幕无码久久综合网| 香蕉视频在线观看免费国产婷婷| 99热在线观看免费| 中国性猛交xxxxx免费看| 羞羞漫画在线成人漫画阅读免费| 亚洲人成综合在线播放| 亚洲欧洲日韩不卡| 亚洲中文字幕久久精品无码喷水| 免费在线观看亚洲| 四虎影院免费视频| 99视频在线精品免费观看6| 免费A级毛片无码A∨免费| 国产成人无码区免费网站|