简化JDBC的使用(1)

类别:Java 点击:0 评论:0 推荐:

这是年前写的旧闻,或者更应该算是自己写的工具的简单文档。本文的题目有点大,并非是解决所有的问题。而仅仅只涉及JDBC的使用,呵呵。那些熟悉OR mapping,或正在使用这类工具的兄弟们不要笑话。毕竟,我们还是有很多机会去直接使用SQL+JDBC的,希望对大伙有帮助。工具的源代码请与我联系,欢迎交流。(主要是我不知道怎么传附件,呵呵)

简化JDBC的使用(1)

胡键([email protected])

西安烁程软件有限公司

2003年12月

前言

       JDBC为java程序提供了访问数据库的统一接口,增强了java数据库应用程序的可移植性,大大方便了java数据库编程。但是在实际应用中,我们仍然面临着一些问题:

²        JDBC强大的功能、复杂的接口,带来了学习的负担;

²        而且与JDBC相关的程序代码(如增、删、改)在不少地方大同小异,如何封装这些代码,使之在实际应用中能被复用?

²        在数据库应用的开发过程中一些常用的功能JDBC目前尚未支持,如数据分页、常用格式的输出(XML、CSV等);

笔者针对这些问题编写了相应的工具类,使之能简化JDBC的使用,并包含了数据库开发过程中的常用的功能。工具包的主要特性:

简化JDBC的使用,使新手能快速上手编写数据库应用; 将最常用的代码(创建连接、增删改、调用存储过程)封装不必每次重复书写相似的代码; 提供了离线的数据对象,在浏览数据的过程中不必维持数据库连接; 数据对象提供“行*列”的数据组织形式,方便数据设置和读取; 提供数据分页功能,非常适合web数据库应用的开发; 支持XML,很方便的与其他技术如XSLT结合,转换成其他格式如HTML; 支持最常用的CSV格式输出; 问题与解决办法

       这部分展示了工具类的设计和应用。

创建数据库连接

       数据库连接为数据库的各种操作提供了最基本的环境。在JDBC中创建数据库连接的最常用方式是:使用JNDI和使用数据库连接参数集(包括:数据库驱动、数据库URL、数据库用户、与用户相对应的密码)。工具包针对这两种情况提供了相应的创建函数,为数据库连接的创建提供了统一的创建入口。在实际使用过程中,不必再为每次连接的创建重复的书写类似的代码。

       在工具包,由ConnectionFactory负责数据库连接连接的创建。根据这两种方式,分别提供了2个创建函数:getConnectionByParams和getConnectionByJNDI。根据实际情况,由用户选择对应的函数来创建连接。

应用举例

1.       使用数据库连接参数:

Connection conn= ConnectionFactory.getConnectionByParams(

"org.gjt.mm.mysql.Driver",

                "jdbc:mysql://localhost/dbformstest", "sa", "");

2.       使用JNDI:

Connection conn= ConnectionFactory.getConnectionByJNDI(

"java:comp/env/jdbc/OracleDS");

数据库基本操作

       数据库的基本操作是:查询、增加、修改、删除和调用存储过程。工具包以DbCommand对象封装了这些操作。在描述它是这些操作之前,我们必须先解决数据的组织方式。

数据对象

       有操作,就有被操作的对象。在数据库应用中,被操作对象就是数据。如何把这些数据组织起来进行有效的操作是我们必须解决的首要问题。在JDBC中,数据是以ResultSet的形式组织起来的。

ResultSet的功能十分强大,但是它并不是没有缺点。首先,要使ResultSet的数据有效,必须维持连接。保持数据库连接,对于ResultSet中包含大量数据的情况下是十分有用的。然而常见的情形是,ResultSet包含的数据并不多。为了能尽快的释放连接,我们通常是先将ResultSet的数据取出,然后释放。频繁的书写这样的代码,对于程序编写者来说实在是缺乏乐趣。;其次,ResultSet支持的数据类型非常丰富,但是针对常用的数据类型(字符串类型、数字类型、时间类型)来说“过于丰富”;对于习惯的“行*列”方式,ResultSet并没有提供好用的接口。

       结合实际的使用情况,工具包将操作数据组织成DataSet。DataSet的特性:

²        保持数据无需维持数据库连接;

²        提供以“行*列”组织的数据获取函数;

²        由数据和元数据组成;

²        返回的数据以String对象保存,因为对于常见的数据类型String足以处理;

²        支持常见的数据类型的操作,以及格式扩展。因为每个数据库对于时间类型的处理不太一样,如SQL Server在增加一条日期数据时可作为字符串处理,而Oracle必须使用to_date函数。但这部分的代码书写量是非常少的。缺省情况下,工具包将日期类型作为字符串处理;

工具包中的数据对象部分的UML图如下:

其中每个对象的作用分别是:

²        DataSet,外部操作的最主要对象。是DataRow和MetaData的容器;

²        DataRow,列数据容器;

²        MetaData,元数据对象,是ColumnMetaData的容器

²        ColumnMetaData,列元数据,包含Format接口;

²        Format,数据SQL语句格式化接口;

²        StringFormat,字符串SQL语句格式化对象;

²        NumbericFormat,数字SQL语句格式化对象;

²        DateTimeFormat,时间SQL语句格式化对象;

通过这种方式,我们把数据组织起来。之后,我们结合数据库操作对象看看具体的应用。

应用举例

1.  查询数据

Connection conn= ConnectionFactory.getConnectionByParams(

                "org.gjt.mm.mysql.Driver", "jdbc:mysql://localhost/dbformstest", "sa", "");

DbCommand cmd= new DbCommand( conn);

DataSet ds = cmd.query("select * from service");

conn.close();

String[][] data1= ds.getData();

在执行查询操作时,DbCommand负责DataSet以及各组成对象的创建。这样,使用者不仅获得相关的数据,同时也获得了与这次查询相关的元数据描述。这种方式也提供了一种自动创建元数据的方式(与自动创建相对的就是手工创建DataSet的元数据):

DataSet ds= cmd.query("select * from service where 1=2");

这条查询语句不会返回任何数据,但是通过它却能获取元数据。只需要将其中的“*”替换成相关的列名,那么就可获得这些列名的数据库描述。这一点,在下面的例子中,读者可以看到实际的应用。

创建DataSet的基本算法是:

根据查询语句获得ResultSet; 将ResultSet的数据抽取出来,获得数据; 获得ResultSetMetaData,根据不同的列类型使用FormatFactory创建对应的Format; 根据元数据的信息创建ColumnMetaData; 把这些信息组装成DataSet返回;

在此,使用FormatFactory创建Format就是为了根据不同的列类型创建不同的Format,使之为数据写操作服务。FormatFactory中只有一个方法createFormat,传入的参数类型是java.sql.Types。通过自定义FormatFactory,使用者可以支持更多的不同类型的列。如果是使用手工创建DataSet的元数据,这一步是可以省略的,只需要实现不同的Format即可。这一点在下面的例子中会给出相应的代码。

2.  增加数据

数据库增、改操作都是使用DataSet来实现的,使用者通过组装不同DataSet,即可把DataSet的数据写入数据库中。

Connection conn= ConnectionFactory.getConnectionByParams(

                "org.gjt.mm.mysql.Driver",

                "jdbc:mysql://localhost/dbformstest", "sa", "");

DbCommand cmd= new DbCommand( conn);

//自动获取元数据(当然也可手动添加)

DataSet ds= cmd.query("select * from service where 1=2");

String[][] data1= {{"400", "dog walking", "talking the dog for a walk"}};

//设置表名

ds.getMetaData().setTableName("service");

//设置数据

ds.setData( data1);

cmd.insert( ds);

conn.close();

DataSet的数据可以通过getData/SetData来获取/设置。使用形式都是最熟悉的2维数组。此外DataSet也提供了相应的Iterator,允许使用者来遍历数据。

3.  修改数据

修改数据的方式与增加数据的方式非常类似,唯一不同的就是需要添加条件。其中条件也是以数组的方式组织,它的维数与DataSet的行数相同,也就是每一个条件对应一行数据。

Connection conn= ConnectionFactory.getConnectionByParams(

                "org.gjt.mm.mysql.Driver",

                "jdbc:mysql://localhost/dbformstest", "sa", "");

DbCommand cmd= new DbCommand( conn);

//自动获取元数据(当然也可手动添加)

DataSet ds= cmd.query("select * from service where 1=2");

//设置更改条件

String[] conditions= {" id= 100"};

String[][] data1= {{"301", "dog walking", "talking the dog for a walk"}};

//设置表名

ds.getMetaData().setTableName("service");

//设置数据

ds.setData( data1);

cmd.update( ds, conditions);

conn.close();

4.  删除数据

删除数据恐怕是最简单了,只需要传入一条sql语句即可。DbCommand提供了execute方法了执行sql命令。

Connection conn= ConnectionFactory.getConnectionByParams(

                "org.gjt.mm.mysql.Driver",

                "jdbc:mysql://localhost/dbformstest", "sa", "");

DbCommand cmd= new DbCommand( conn);

cmd.execute("delete from service where id= 400");

conn.close();

本文地址:http://com.8s8s.com/it/it16732.htm