首页 > Berkeley DB JE, Haomian Wang > BDB Java Edition + prefuse, 轻松实现数据可视化

BDB Java Edition + prefuse, 轻松实现数据可视化

2010年3月8日 haomianwang

数据可视化概述

这些年来,随着大量数据的产生,数据可视化(data visualization)广泛应用于科研、军事、金融、医疗等等领域。我们的生活也到处可见数据可视化的例子。比如,股票软件上显示的K线图,调查结果的柱状图、曲线图,人口分布的密度图等等等等。

那么,什么是数据可视化呢?根据维基百科的解释:Data visualization is the study of the visual representation of data, meaning “information which has been abstracted in some schematic form, including attributes or variables for the units of information”。简单来说,数据可视化就是用更加直观更加生动易懂的图形图像表现某种特定的数据集合。

这篇文章将简单介绍如何轻松利用BDB Java Edition (JE)和prefuse实现自己的数据可视化应用。

可视化工具和数据库的选择

首先我们选择prefuse作为数据可视化工具。prefuse是一个轻量级的用于可视化任意数据集(visualize the data)的java类库,它提供了多种数据可视化模式,比如柱状图、树图、饼图等等。它的优点是简单易用、可视化功能齐全。

但仅仅有可视化工具是不够的,还需要什么呢?当然还必须有存储数据的数据库。可以打个比方,数据是一栋房子,数据可视化就是我们要给房子做装修,让它更好看,那么数据库就是地基。没有地基,何来房子,更不用说装修了。那么,我们选择什么样的数据库呢。既然prefuse是java类库,而我们JE的特点是纯Java实现,性能高,footprint小等等,那么,JE绝对是一个很好的选择。

好了,现在就让我们看看JE + prefuse的威力吧。

数据集属性的定义

首先,我们选择需要做可视化的数据集。在这里,我给出的例子是可视化某个公司的员工数据,包括他们的基本属性,上下级关系和各自所参与的任务。

1. 员工(Employee)的属性

@Entity
public class Employee {
    @PrimaryKey
    int employeeId;

    @SecondaryKey(relate = MANY_TO_ONE)
    String employeeName;

    @SecondaryKey(relate = MANY_TO_ONE)
    float salary;

    @SecondaryKey(relate = MANY_TO_ONE, relatedEntity=Employee.class,
                 onRelatedEntityDelete=NULLIFY)
    int managerId;

    @SecondaryKey(relate = MANY_TO_ONE, relatedEntity=Department.class,
                 onRelatedEntityDelete=NULLIFY)
    int departmentId;

    @SecondaryKey (relate =MANY_TO_MANY, relatedEntity=ServiceRequest.class,
                 onRelatedEntityDelete=NULLIFY)
    Set<Integer> SRIds = new HashSet<Integer>();

    String address;
    String email;
    String phone;

    /* setter and getter functions. */
}

2. 部门(Department)的属性

@Entity
class Department {
    @PrimaryKey
    int departmentId;

    @SecondaryKey(relate = ONE_TO_ONE)
    String departmentName;

    String location;

    /* setter and getter functions. */
}

3. 任务(ServiceRequest)的属性

@Entity
class ServiceRequest {
	@PrimaryKey
	int SRId;

	String title;
	String content;

/* setter and getter functions. */
}

数据可视化效果

我们选择两种可视化方式:弧形树(radial tree)和节点树(node link tree)。下面看看我们的可视化效果。

利用radial tree来显示整个公司的结构(organization chart):

上图左边最大的窗口显示的是整个公司的结构图。从图中可以看出公司有四个部门。每一个有颜色小节点代表一名员工,不同部门的员工具有不同的颜色。节点之间的连线表示上下级关系。上图右上角的小窗口显示的是选中的员工的具体信息。右下角的小窗口显示的是JE database 的schema图。从中可以看出我们定义了三个Entity: Employee, Department以及Service Request.

点击任意一个员工节点,将可以显示此员工的上下级结构图,也就是在此公司与之有关系的所有员工的结构图。比如我们点击名字叫Goodstein A. Chavez 的员工,结果如下图所示:

从上图可以看出,此员工有四名直接下属,而他的老板直接向公司的CEO汇报。

除了可以直接点击员工节点(基于员工ID)进行查询,我们还可以通过部门ID(Department ID)经理ID(Manager ID)和具体的任务ID(SR ID)和员工姓名来对员工进行查询。下面是对部门ID和任务ID查询的结果截图。

部门2的员工结构图(DeparmentID = 2)

部门2中,参与了任务3的员工(DeparmentID = 2 and SRId = 3)

值得一提的是,所有这些关系的查询都可以利用在JE里面定义的Entity之间的关系(relation),而不需要我们做额外的查询工作,比如想通过经理ID来查询此经理的直接下属,一句代码便可以实现:

dao.employeeByManagerId.subIndex(Integer.valueOf(searchKey)).entities();

JE+prefuse的优势总结

  1. 简单易用:用过JE的朋友都知道,利用JE(特别是JE DPL)能够十分轻松、灵活定义各种数据集模型,其get/put操作也特别简单,而且能够很容易写出特定的查询语句。而prefuse也提供了功能齐全的可视化API。所以,利用JE做数据的存取操作,利用prefuse做数据的可视化操作,其对接是十分直接和简便的。
  2. Footprint小:拿上面所举的员工数据可视化应用例子来说,整个应用程序打成可直接运行的jar文件才1.87M,但功能却很齐全(多种可视化效果,多种查询方式)。这样大小的程序,即使安装在一般的移动设备(比如手机)上运行都绰绰有余。
  3. 性能高:数据可视化的性能主要体现在做查询和可视化的速度。还是以员工数据可视化为例,插入员工数据有1000条,存储到JE 数据库的大小是729k。之后用户对节点的点击和在输入框的查询,其可视化结果都能迅速得以显示(笔者没有做过具体的时间记录,但相信所需时间都是毫秒级的)。

结束语

从这个例子我们可以看出在数据可视化方面,利用JE作为存储引擎是一个很好的选择。有兴趣的朋友不妨一试。另外,这里有一个十分有趣例子,是利用JE和Google Visualization API来可视化一栋房子的用电情况( electric usage of Hypatia House),感兴趣的朋友请参考以下链接:http://excitedcuriosity.wordpress.com/2010/02/22/its-electric-ted-data-storage-and-plotting/

分类: Berkeley DB JE, Haomian Wang 标签: ,
  1. strayly
    2010年4月20日11:21 | #1

    想请教关于bdb je在tomcat web应用的问题

    我有一个非web程序 打包成jar 定时向bdb中添加数据,但是web中确不能读取新的数据,只有重启tomcat才能读取
    非web程序,可以读取的
    不知道为什么,如何才能让tomcat中的web读到新数据呢

  2. haomianwang
    2010年4月20日18:54 | #2

    @strayly
    您好。

    通过你的描述,我们很难指出问题所在。希望你能提供更多的信息。比如,你的tomcat版本和JE版本,你的web 程序和jar 程序是什么样子?

    如果可能,希望你能提供测试代码(包括web程序 和 jar 程序)。

    谢谢。

  3. haomianwang
    2010年4月20日18:56 | #3

    @strayly
    你可以参考下面链接,关于如何在JSP程序中使用BDB JE:
    http://reecegriffin.com/blog/berkeleyje.html

  4. strayly
    2010年4月21日05:21 | #4

    @haomianwang
    谢谢您的回复,我在oracle官方论坛也看了,也有人提过类似的问题
    就是同一个DB 有两个程序访问(我这里一个是jar程序,一个是web程序),一个以写模式,一个以只读模式
    如果写程序更新了数据,读的程序是看不到这个变化的
    http://www.oracle.com/technology/documentation/berkeley-db/je/GettingStartedGuide/multiprocess.html
    像我这种情况该怎么解决?我的web app 可以访问到我的后台jar程序的Environment对象吗

  5. haomianwang
    2010年4月21日11:08 | #5

    @strayly
    如果写程序更新了数据,读程序要想看到变化,必须关闭Environment,然后重新开启,也就是你重启tomcat的过程。

    如果你不想重启tomcat,那么在你的web 程序中,是否可以设置一个刷新命令,每次刷新就是重启Environment的过程(注意,这将会导致性能的问题)。或者你可以参考我第一次回复的帖子中的链接提到的例子。

    另外一个方法在官方论坛上我们的工程师也提到过:use a single process: change your web app so that it includes the functionality of your command line app.

  6. strayly
    2010年4月21日11:24 | #6

    @haomianwang
    非常感谢您的热心回复,设置一个刷新命令,这个不是太好,因为关闭Environment的过程是比较耗时的,
    如果在这个过程中,前台用户访问就会报错了。
    use a single process: change your web app so that it includes the functionality of your command line app.
    英语不是太好,这个意思是不是说,修改web程序,让web程序访问后台程序的Environment?
    web程序可以访问后台java程序的Environment吗?怎么访问呢

  7. haomianwang
    2010年4月21日14:04 | #7

    @strayly
    首先一点,对于web程序来说,它有很多种。JSP?JavaScript?PHP?

    另外,您可以参考下面这个链接(基于BDB的JSP应用):
    http://reecegriffin.com/blog/berkeleyje.html

  8. hanyu zhang
    2010年5月5日10:24 | #8

    你好,我是一名学生,最近准备一份project,我想问一个很弱的问题,怎样用ECLIPSE或者XCODE 与BDB连接?
    然后怎样用ECLIPSE建立数据库,插入数据,插入属性,模糊搜索。
    我是一名初学者,最好能写一下详细步骤或者给一些参考资料(中英都行)
    非常感谢您的帮助,我已经奋斗了两天两夜了,在线等您答复
    我现在是凌晨4点23分。。。。。
    感激不尽。

  9. hanyu zhang
    2010年5月5日10:24 | #9

    哦 对了 说明一下 我是MAC系统,如果能写MAC系统的步骤更好不过了。谢谢您

  10. haomianwang
    2010年5月12日12:53 | #10

    @hanyu zhang
    您好,感谢你选择使用BDB JE。

    首先,必须明确一点,BDB JE是一个嵌入式数据库,它和你的应用程序绑定在一起,也就是说,你不需要在客户端通过连接数据库server来使用BDB。
    简单说来,使用BDB JE和使用任何java类库是一样的:将它直接包含进你的应用程序。

    大概的步骤如下(如何在Eclipse中使用BDB JE):
    1.下载Berkeley DB Java Edition:http://www.oracle.com/technology/software/products/berkeley-db/index.html
    2. 解压缩下载包,你可以在解压缩包的lib文件夹中看到几个jar文件,其中有类似于je-4.0.103.jar。备注:这里4.0.103具体指JE的版本号,视具体情况会有差异。
    3. 在Eclipse中将je-4.0.103.jar加进你的project路径,方法和添加其他外部jar文件一样。也就是Projet->Properties->Java Build Path->Add Extenal Jars,选择之前解压缩目录下的je-4.0.103.jar。

    这样你就可以在你的project中使用BDB JE了。

  11. colo
    2010年5月16日19:34 | #11

    请问,能将你们这个例子的源码发给我看下吗,我最近在学这个,谢谢了!

  12. colo
    2010年5月16日19:35 | #12

    就是BDB JE +prefuse的例子

  13. haomianwang
    2010年5月17日11:38 | #13

    @colo
    你好,感谢你关注BDB JE。

    由于某些原因,我不能和你共享这些源码。我可以给你一些建议:

    1. 在项目中使用BDB JE 和 prefuse都十分简单,因为它们都是java类库。所以,你只要把这两个类库je.jar和prefuse.jar加入你的项目中,便可以使用它们了。

    2. 不知道你之前是否使用过BDB JE和prefuse。即使你之前没有接触过,我相信,只要你有一定的编程基础,你都可以很快上手,因为它们都是十分简单易用的。

    关于BDB JE的学习,你可以阅读下面这个文档:
    http://www.oracle.com/technology/documentation/berkeley-db/je/GettingStartedGuide/BerkeleyDB-JE-GSG.pdf
    关于prefuse的学习,你可以阅读下面这个文档:
    http://prefuse.org/doc/manual/

    3. BDB JE + prefuse的基本思想是,利用BDB JE来实现数据的存储和读取,然后用prefuse做数据可视化。因为对于prefuse来说,它默认的数据存储方式是XML,然后通过读取XML文件来获得需要可视化的数据。在这里,我用BDB JE来代替XML来存储数据。

    如果你在使用BDB JE + prefuse过程中遇到什么技术上的问题,欢迎一起探讨。

  14. colo
    2010年5月17日15:56 | #14

    太感谢你了,谢谢,我会好好研究下的

  15. colo
    2010年5月18日16:17 | #15

    请问可以用prefuse+BDB做可视化显示吗
    我页面是JSP的,从BDB读出来的数据是一个一个类的形式或者字节流
    请问怎么样能利用prefuse显示
    我看到prefuse主页上的是xml和jdbc连接的例子,不知道这样要怎么实现,谢谢了

  16. colo
    2010年5月18日16:18 | #16

    从BDB读出来的数据我把它封装成了一个一个的java类
    请问这样要怎么实现prefuse可视化,谢谢

  17. chaohuang
    2010年5月18日17:36 | #17

    你可以给Eric发邮件: haomian.wang[at]o***le.com

  18. colo
    2010年5月19日18:26 | #18

    不好意思又来打扰了
    请问你们这个例子中从BDB JE中读出来的数据是什么类型的,是java对象还是字节流
    是java对象的话要怎么样提供给prefuse显示,字节流是先转换成xml文件格式再提供给prefuse显示吗
    谢谢谢谢了,感激不尽

  19. haomianwang
    2010年5月21日13:10 | #19

    @colo
    您好,不需要把BDB JE的数据转成xml格式。

    事实上,prefuse读取xml文件其实是为了读取其中的数据和数据之间的关系(对于图Graph来说,也就是节点和边)。所以,在可视化的时候,你只要提供这种关系,prefuse便可以进行可视化处理。

    更具体一点,比如你用Grpah的形式进行数据可视化。那么首先你利用BDB JE的API读取出之前存储的数据,包括数据本身的值(节点),以及数据之间的关系(节点与节点之间的联系)。你把这些数据提供给prefuse,prefuse可以把它组装成一个Graph,然后进行可视化显示.

    如上面的例子,我现在要显示的是员工图。那么首先,我用BDB JE API读取出每个员工的信息(姓名、电话等等),比如有1000个员工,那么我就有1000个Nodes(也就是1000个Employee对象),然后我再提供这些员工的关系(比如以经理来分类,经理和他的属下所代表的节点连一条边),这样你就可以得到许多条Edges(比如100条)。你便可以利用这些Nodes 和 Edges生成一个Graph:

    Table nodes = ……(利用读取的1000个Employee对象的信息生成1000个nodes);
    Table edges = ……(利用提供的关系生成100条edge);
    Graph employeesGraph = new Graph(nodes, edges, yes);

    最后,便可以利用prefuse的API来可视化显示生成的Graph.
    注意,这里的Table 和 Graph类都是prefuse的类。

  20. 鸭蛋
    2010年5月26日10:37 | #20

    你好,我现在做一个《音频信息可视化软件》,我用的数据库是SqlServer,而不是xml。请问这样的话,还可以使用prefuse实现数据的可视化(主要是要产生树状的音乐树)吗?

  21. 鸭蛋
    2010年5月26日10:39 | #21

    @鸭蛋

    补充下,我的开发平台选用的是Eclipse

  22. chaohuang
    2010年5月26日13:04 | #22

    @鸭蛋
    如果你能从SqlServer提取到节点以及节点之间的关系的话,可以很容易使用prefuse实现数据的可视化。

    当然,能否从SqlServer提取节点关系等信息,以及如何使用prefuse和本博客不相干。请咨询SqlServer和prefuse。

  23. 鸭蛋
    2010年5月26日14:40 | #23

    谢谢……O(∩_∩)O

  24. 鱼几个木
    2010年9月17日11:05 | #24

    你好,我没有使用BDB JE。
    向你咨询一个问题:我使用prefuse从Oracle中读取数据,代码如下:
    ConnectionFactory.getDatabaseConnection(driver,url,userName,userPwd).getData(“select * from tableName”) ;
    报异常:Type double not supported.
    数据库字段类型为:number,varchar2,varchar2。把number改为int型也是报告同样异常。
    请问怎么解决?谢谢了!

  25. chaohuang
    2010年9月17日11:33 | #25

    @鱼几个木
    你好,这里是BDB的论坛。我看上去你的问题是在Oracle RDBMS,请到asktom.oracle.com咨询Oracle RDBMS的专家。

  26. 鱼几个木
    2010年9月17日15:27 | #26

    @chaohuang
    谢谢!!

本文的评论功能被关闭了.
Դ