JDBC 提供了一种强大、全面的接口用来从 Java 程序访问数据库。对于较小的项目来说,使用 JDBC 似乎是理所当然的,它使一些程序员避免了同时使用数据库。本文描述了一种简单的包装器库,它让使用简单的数据库易如反掌。您会发现您已经开始想在编写的每一个程序中都使用 JDBC。
事情发生得很突然。您正在修改一个程序,您原以为它是个小程序,不料竟发现它已经迅速增长成为一个庞大的东西 ? 一个项目 ? 而现在您已到了需要保存一些数据的时候了。
问题是,您并不是有意让程序发展到这种程度的。 您只是不由自主地做了一小部分修改。您并没有真正准备要存储或装入。而且,您的程序是个 applet,而 applet 是无法存储或装入的。
可以存储或装入它们吗?
实际上,JDBC API 允许任何 Java 程序 ? 甚至是 applet ? 连接到关系型数据库(RDBMS)上。 不幸的是,JDBC 对您的小程序来说可能有一点头重脚轻了。毕竟,如果您希望做的只是存储一点点数据的话,RDBMS 是一个强大、复杂的系统。
在本文中,我们将分析一个简单的使用 JDBC 的抽象层。对于简单的应用程序来说,它可以让您只用几行代码就实现存储和装入结构化数据。它不会处理复杂的 RDBMS 使用,但那正是我们要避免的,不是吗?
JDBC 的复杂性
JDBC 使用起来可能是一个复杂的 API。它不仅必须支持整个强大的 SQL 标准,还必须很好地隐藏不同数据库引擎之间的区别。
JDBC 的复杂还在于关系型数据库是基于 SQL 构建的,而 SQL 是要给人用的,而不是给程序用的。直接使用 JDBC 有点象同时用两种语言编程。
虽然 JDBC 的这些方面并不是什么坏事,但它们确实与我们的目标 ? 快速地存储少量数据相冲突。
简化的抽象
我们将创建一个简单的抽象层,让您不必顾虑所有繁琐的细节问题来直接使用 JDBC。如果您早已熟悉 JDBC 或关系型数据库了,那您一眼看到我们的类列表应该是很熟悉的:
Database
Table
RowSet
Row
我们这里不是在作任何实质性的事情;我们的数据模型本质上和关系型模型是一样的,但去掉了烦人的细节(同时去掉了强大的功能)。每一个类映射到一个基本的 RDBMS 概念上,同时也映射到一个 JDBC 类上。就是这种映射让我们的 API 可以在保持易用性的同时保留它的相关特性。
这种 API 的设计是基于对我们的数据存储需要的设想。如果您发现自己的程序需要一点不同的地方,您可以随意地改变这种抽象以适应您的情况。 这些类可以被认为是一种简化您工作的模式,而不是一成不变的规则。
如果您不熟悉 SQL 或者 RDBMS 技术,不必害怕。 下面的四节中,每一节都会帮助您熟悉我们的一个类,还有这些类映射到的 RDBMS 功能。
Database 类
当使用 JDBC 与数据库建立连接时,您必须告诉 JDBC 在何处可以找到实际的数据。 因为不同的数据库引擎有不同的访问方法和描述这些方法的不同语法,所以有不止一种方法来指定数据源。 在 JDBC 中,统一资源标识符(Uniform Resource Identifier,URI)字符串是用来指定数据源的,而这个字符串的结构是依赖于数据库的。
Database 类的主要目的就是封装这个字符串,还有建立连接操作时可能需要的任何用户名/密码信息。
下面是如何创建一个 Database 对象的方法:
Database db =
new Database( "jdbc:postgresql://localhost/mito",
"mito", "" );
构造函数的第一个参数是数据源的 URI。 在这个示例中,我使用了 PostgreSQL 数据库引擎,而且在本机上访问了一个名为 mito 的数据库。 另外,我指定我的用户名 mito 和一个空的密码分别作为第二个和第三个参数。
一旦您创建了 Database 对象,您就可以使用它来访问数据,如我们在下一章可以看到的一样。
Table 类
我们在 API 中对简化的一个设想就是,当您从表的一行读取数据时,您会得到整行的数据。换句话说,表的一行是作为读写单独一块数据的最小单位。这并不十分有效,但效率不是我们方法中所首要考虑的。
Talbe 类让您可以读写这些行对象。您必须做的第一步是创建一个表对象,它简单得只要知道它的名称即可:
Table table = db.getTable( "employee" );
创建 Table 对象的操作实际上并没有做任何事,只是让对象记住自己的名称。要做一些实际的事,我们就需要实际地使用这个 Table 对象了。在这里,我们从表中读取一行。
Row row = table.getRow( "id=101");
注意,我们已经指定了我们只需要那些‘id'值设定为‘101'的行。通过使用 getRow() 方法,我们假定只有一行符合这个条件。在另外的情况下,我们可能需要多个行,那样我们就需要这样使用 getRows() 方法:
RowSet rows = table.getRows( "id<103" );
在这种情况下,返回的值是一个 RowSet,而不是一个 Row。RowSet 就是 Row 的一个集合。
在接下来的两节里,我们将讨论 Row 和 RowSet 类。
Row 类
在我们的抽象中,Row 是在 RDBMS 中表示表中一行的名称/值对的集合。不同于 RDBMS 值可以是不同的类型,Row 仅包含一种类型,即字符串类型。 这还是为了让事情简单一点 ? 我们假定您不需要字符串类型提供的任何更强大的功能。
一旦您有了一个 Row,就很容易从其中取出一个值,正如我们在清单 1 中看见的一样。
清单 1. 从 Row 中获取值
Row e = table.getRow( "id=100" );
String name = e.get( "name" );
System.out.println( "Employee name: "+name );
还要注意的是 Row 是排序的,这样您就可以通过索引来取出名称/值的对。清单 2 中给出了这样的一个示例。
清单 2. 迭代整个 Row
Row e = table.getRow( "id=100" );
for (int i=0; i<e.length(); ++i) {
String key = e.getKey( i );
String value = e.get( i );
System.out.println( key+" = "+value );
}
当然,您还可以改变 Row 中的值。这是在数据库中更改数据所必需的 ? 稍后我们会看到这一点。
RowSet 类
记住有一些查询可以返回多个 Row,这样的话您就会得到一个 RowSet。RowSet 有一点不同于基于 Vector 的包装器。你可以轻易地迭代 RowSet 中所有的 Row,在清单 3 中可以看到这一点。
清单 3. 迭代整个 RowSet
RowSet rs = table.get( "id<104" );
for (int i=0; i<rs.length(); ++i) {
Row row = rs.get( i );
// do something with the row....
}
(未完,待续)
文章来源于领测软件测试网 https://www.ltesting.net/