记得刚学Jasperreport的时候,在谷歌和百度上搜到的大多数入门文章都是教授如何使用数据库来做报表的。对于只采用简单数据集和那些直接面向数据的报表,使用数据库作为数据源是合适的;但是也有很多的报表不是直接面向原始数据的,例如财务报表,都是需要计算和做后续处理;也有一些报表引用的数据粒度小,但是数量多,使用数据库做数据源是不合适的。
XML一直被认为是一种很好的描述结构化数据的语言。
首先XML文件的数据结构非常清晰。可以把报表所需要的数据集成到一个XML文件上,然后再通过在文件内查询,这比每需要一条数据就使用SQL来查询要显得更高效和简单。试想一下,你的同事A告诉你,“报表的数据都在这份XML文件里哦”。而同事B则对你说:”那些数据在某个数据库里,你自己去查吧。“,你更喜欢听到哪一句呢?(当然我的语气上的差别就说明了我的喜好,我老怀疑后者在背向我的那一刻有在奸笑。)
其次,现在对象映射到XML的工具很多。哦?你知道我在暗示什么吗?没错,你可以面向对象,而不用面向丑陋的表格。在上一篇文章中,我给出这样一个数据源。
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类。大概像下面这样。
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文件。
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类代码。
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:“哎,你给我说清楚点再走……”