記得剛學Jasperreport的時候,在谷歌和百度上搜到的大多數入門文章都是教授如何使用數據庫來做報表的。對於只采用簡單數據集和那些直接面向數據的報表,使用數據庫作為數據源是合適的;但是也有很多的報表不是直接面向原始數據的,例如財務報表,都是需要計算和做後續處理;也有一些報表引用的數據粒度小,但是數量多,使用數據庫做數據源是不合適的。
XML一直被認為是一種很好的描述結構化數據的語言。
首先XML文件的數據結構非常清晰。可以把報表所需要的數據集成到一個XML文件上,然後再通過在文件內查詢,這比每需要一條數據就使用SQL來查詢要顯得更高效和簡單。試想一下,你的同事A告訴你,“報表的數據都在這份XML文件裡哦”。而同事B則對你說:”那些數據在某個數據庫裡,你自己去查吧。“,你更喜歡聽到哪一句呢?(當然我的語氣上的差別就說明了我的喜好,我老懷疑後者在背向我的那一刻有在奸笑。)
其次,現在對象映射到XML的工具很多。哦?你知道我在暗示什麼嗎?沒錯,你可以面向對象,而不用面向丑陋的表格。在上一篇文章中,我給出這樣一個數據源。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <NameList>
3 <Person>
4 <Name>強尼</Name>
5 <Gender>男</Gender>
6 <Age>56</Age>
7 </Person>
8 <Person>
9 <Name>阿美</Name>
10 <Gender>女</Gender>
11 <Age>23</Age>
12 </Person>
13 <Person>
14 <Name>李麗</Name>
15 <Gender>女</Gender>
16 <Age>58</Age>
17 </Person>
18 <Person>
19 <Name>傑森</Name>
20 <Gender>男</Gender>
21 <Age>32</Age>
22 </Person>
23 <Person>
24 <Name>劉三</Name>
25 <Gender>男</Gender>
26 <Age>21</Age>
27 </Person>
28 </NameList>
如果你是個典型的面向對象的思考者,應該馬上想到一個叫Person的Java類。大概像下面這樣。
1 package com.blogjava.heis.jasper.chapter2;
2
3 public class Person {
4
5 private String name;
6 private String gender;
7 private int age;
8
9 private String getName() {
10 return name;
11 }
12 private void setName(String name) {
13 this.name = name;
14 }
15 private String getGender() {
16 return gender;
17 }
18 private void setGender(String gender) {
19 this.gender = gender;
20 }
21 private int getAge() {
22 return age;
23 }
24 private void setAge(int age) {
25 this.age = age;
26 }
27 }
想像一下,把一個個對象排著隊跳進模板,然後一張完整的報表就出來了,不用管那些煩人的Sql,那應該是多麼美好的一件事兒。面向對象果然是我們的福音。接下來看看我們如何把對象轉換成XML文件。
package com.blogjava.heis.jasper.chapter2;
import java.io.File;
import java.io.FileWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import org.apache.commons.betwixt.io.BeanWriter;
public class BeanToXMLConverter {
private final static String FILE_PATH="c:/test.xml";
/**
* Create an example bean and then convert it to xml.
*/
public static final void main(String [] args) throws Exception {
Person person1=new Person();
person1.setName("張三");
person1.setGender("男");
person1.setAge(35);
Person person2=new Person();
person2.setName("李四");
person2.setGender("女");
person2.setAge(25);
ArrayList<Person> al=new ArrayList<Person>();
al.add(person1);
al.add(person2);
NameList nameList=new NameList();
nameList.setList(al);
try{
BeanToXMLConverter wea=new BeanToXMLConverter();
wea.writeToXMLFile(nameList);
}catch(Exception e){
e.printStackTrace();
}
}
private void writeToXMLFile(Object obj)throws Exception{
StringWriter outputWriter = new StringWriter();
outputWriter.write("<?xml version='1.0' ecoding='UTF-8' ?>\n");
BeanWriter beanWriter = new BeanWriter(outputWriter);
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
beanWriter.getBindingConfiguration().setMapIDs(false);
beanWriter.enablePrettyPrint();
beanWriter.write(obj);
String xmlFilePath=FILE_PATH;
File xmlFile=new File(FILE_PATH);
if(!xmlFile.exists()){
xmlFile.createNewFile();
}
FileWriter fw=new FileWriter(xmlFilePath);
fw.write(outputWriter.toString().toCharArray());
fw.flush();
System.out.println(outputWriter.toString());
outputWriter.close();
}
}
NameList類代碼。
1 package com.blogjava.heis.jasper.chapter2;
2
3 import java.util.List;
4
5 public class NameList {
6
7 private List<Person> list;
8
9 public List<Person> getList() {
10 return list;
11 }
12
13 public void setList(List<Person> list) {
14 this.list = list;
15 }
16 }
17
運行以上的代碼需要四個包,commons-betwixt.jar,commons-logging.jar, commons-collections.jar, commons-beanutils-core.jar。這些都可以從http://commons.apache.org/下載。JDK需要1.5或以上。
看到這裡你心裡也許開始矛盾(或者不屑),對,同事Q也是這樣想的。
Q:“這不是擺明更麻煩麼?對象轉換為XML,再從XML查數據,你這瞎折騰我,浪費資源在轉換上!!”
俺:“也許是多了一些功夫,多占用了點資源。但是這可以讓報表的數據可讀性更強,更重要的是報表制作可以和SQL說拜拜,他和對象走得更密切了。”
Q:“但是你的XML文件不是還是需要查詢麼?你能保證那些查詢語句比SQL更簡單麼?”
俺:“我能給你肯定的回答。但是XML的查詢就要留到下一章去介紹了。這星期OT比較多,先溜啦,88。”
Q:“哎,你給我說清楚點再走……”