用 Apache Derby 进行开发 —— 取得节节胜利: 使用 Apache Derby 进行数据库开发,第 1 部

发表于:2007-05-24来源:作者:点击数: 标签:开发Derby节节胜利取得apache
想要立刻开始使用 Apache Derby 吗?这个由多个部分组成的系列属于 用 Apache Derby 进行开发:取得节节胜利 专栏,它将带领您立刻使用 Derby 数据库。第 1 部分介绍关系数据库的基本概念,并侧重于这些主题与 Derby 数据库的关系。您将学习 ACID 测试 (用一
想要立刻开始使用 Apache Derby 吗?这个由多个部分组成的系列属于 “用 Apache Derby 进行开发:取得节节胜利” 专栏,它将带领您立刻使用 Derby 数据库。第 1 部分介绍关系数据库的基本概念,并侧重于这些主题与 Derby 数据库的关系。您将学习 ACID 测试(用一个简单的示例演示)和 ij 工具,该工具可用于交互连接和查询 Apache Derby 数据库。然后,本系列的测试将帮助您成为使用 Apache Derby 的高手。

关系数据库系统简介

您可以很快就开始开发数据库应用程序,但可能要花一生的时间来掌握它。幸运的是,Apache Derby 是轻量级数据库,您不必用毕生的精力来精通它。按照本文的下列步骤操作之后,就能够开始使用它了。

但本系列的目标不仅仅在于让您入门,而旨在帮助您掌握使用 Apache Derby。首先,应熟悉 ACID 测试,它提供了对关系数据库基本原则的压缩封装。





回页首


ACID 测试

钻石显然是十分贵重的东西,正因为贵重,所以才会严肃对待赝品被。确定钻石是真是假的一个简单而(至少在电影里)流行的测试是让它在一片玻璃上滚。因为钻石是众所周知最坚硬的材料,真正的钻石很容易切割玻璃表面;而赝品,尤其是用玻璃本身制作的赝品,则无法做到。

对软件开发人员来说,数据库也有这么贵重。如果使用数据库的话,需要确保它安全存储数据并允许您将来检索数据。您还希望数据库允许多个程序使用数据库而不会相互干扰。为了演示,假设您拥有一个银行。银行的数据库必须具备下列功能:

  • 安全存储合适的数据
  • 快速检索合适的数据
  • 支持多个并行的用户会话

这些任务可以合称为 ACID 测试;ACID 是 Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)和 Durability(持久性)的缩略词。

原子性 指数据库操作可以组合到一起,当作单个单元处理。

一致性 保证此单个单元(或事务)中的所有操作要么都成功执行,要么都不执行。换句话说,数据库不能处于未完成状态。要了解这些特征为何如此重要,可考虑这样一个银行事务:即钱从储蓄帐户转到支票帐户。如果在将钱从储蓄帐户减去之后、加到支票帐户之前,转帐处理失败,那么您就会变穷,而银行将会有一个愤怒的(前)客户!原子性使得这两个操作 —— 从储蓄帐户减钱和向支票帐户加钱 —— 被当作单个事务进行处理。一致性保证事务中的这两个操作同时成功或同时失败。这样,您的钱就不会丢失了。

隔离性 指独立的数据库事务集合以不相互冲突的方式执行。仍使用这个银行类比,考虑两个客户同时在帐户之间转移资金。数据库必须分别跟踪两个转帐;否则,资金可能进入错误的帐户,而银行可能得多两个愤怒的(前)客户。

持久性 保证数据库是安全的,不会异常终止。当电源断电时,如果电视或计算机不工作,这可能是小麻烦,但同样的事情对于数据库来说就不一样了。如果银行计算机在转移资金时掉电,导致交易丢失,您就不会是个快乐的客户了。持久性保证如果数据库在资金转移期间异常终止,则当数据库重新启动时,它将能够恢复交易并继续正常的操作。

通过 ACID 测试不容小觑,许多简单的数据库都做不到。对于关键的电子商务或基于 Web 的应用程序,通过 ACID 测试是必不可少的。这就是为什么如此多的公司和个人利用企业级数据库系统(比如 IBM DB2® Universal Database、Oracle 10g 或 Microsoft® SQL Server)的原因之一。这些数据库与 ACID 测试完全兼容。与这些数据库系统相比,Apache Derby 数据库就像是被遗忘的后娘生的孩子一样。但是,Apache Derby 与 ACID 测试完全兼容,您可以放心地使用它开发基于 Web 的数据库应用程序。此外,如果开始使用 Apache Derby,而且您的应用程序(或业务)在增长,则可以毫不费力地将数据库应用程序移植到 DB2 等企业级数据库系统。





回页首


用 Apache Derby 创建数据库

在使用数据库之前,必须创建一个数据库。在 Derby 下载和安装过程中,您会获得几个工具。其中的 ij 是交互式 Java™ 工具,用于与 Apache Derby 数据库服务器通信。下文将展示如何使用 ij 工具执行简单的数据库操作,比如创建数据库。

本系列的第一篇文章 中,学习了如何下载和安装 Derby 软件。如果还没有阅读该文章,那么现在应该读一读。具体来说,按照指导进行下载和安装,才能在计算机上具有 Apache Derby 软件的一个可以工作的版本。

第一篇文章的结尾讨论了如何正确设置系统以使用 Derby 数据库。总之,因为 Derby 是 Java 应用程序,所以必须正确初始化 CLASSPATH 环境变量。可以设置 DERBY_INSTALL 环境变量,然后将相关的 Java Archive (JAR) 文件添加到 shell 初始化文件(比如 .bashrc 文件)中的 CLASSPATH 中,命令如下:

export DERBY_INSTALL='/opt/Apache/db-derby-10.1.2.1-bin'
export CLASSPATH=$DERBY_INSTALL/lib/derby.jar
export CLASSPATH=$CLASSPATH:$DERBY_INSTALL/lib/derbytools.jar:.


通过创建批处理文件可以在 Microsoft Windows® 系统上获得同样的效果,命令如下:

set DERBY_INSTALL=C:\Apache\db-derby-10.1.2.1-bin
set CLASSPATH=%DERBY_INSTALL%\lib\derby.jar
set CLASSPATH=%CLASSPATH%;%DERBY_INSTALL%\lib\derbytools.jar;.


注意:在这两个示例中,CLASSPATH 环境变量的初始化(通过 exportset shell 命令)都用两个步骤完成。这纯粹是因为本文篇幅所限。可以在自己的变量初始化中使用一行或两行。

现在只要打开新命令提示,就可以运行该批处理文件。不管是 Windows 还是 UNIX® 脚本文件,一定要确保正确指定安装 Derby 软件的目录。

正确设置了环境之后,可以运行 ij 工具来创建新的目录,如 清单 1 所示。


清单 1. 使用 ij 工具
rb$ echo $CLASSPATH
            /opt/Apache/db-derby-10.1.2.1-bin/lib/derby.jar:
            /opt/Apache/db-derby-10.1.2.1-bin/lib/derbytools.jar:.
            rb$ mkdir derbyWork
            rb$ cd derbyWork
            rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij> connect 'jdbc:derby:test;create=true' ;
            ij> exit ;
            rb$ ls -CF
            derby.log       test/
            

首先,显示 CLASSPATH 环境变量。这样做有时是避免以后出错的好办法。在这里,Derby JAR 文件明显存在。下一步是创建并更改为可以工作的新目录(在本例中目录叫做 derbyWork,但您可以随意使用任何名称)。这就更容易看清使用 ij 工具创建新数据库时发生的事情。预备工作完成之后,可以开始启动 ij 了。

因为 ij 工具是 Java 应用程序,因此需要启动 Java Virtual Machine (JVM),并指出要运行的相应主类的名称,在这里是 ji 工具。如果获得 Java 异常,则重新检查 CLASSPATH 以确保 derbytools JAR 文件存在。

当 ij 工具启动时,显示版本信息并提供提示符,提示符默认情况下是一个大于符号 (>)。在该提示符下,运行 connect 命令,连接数据库。connect 命令需要一个指示符字符串用于查找要连接的数据库。在本例中,该连接字符串是 jdbc:derby:test;create=true。正式地,该字符串称为 Java Database Connectivity (JDBC) URL。(JDBC 是一种 Java 技术,允许 Java 应用程序与数据库通信。)

对 JDBC URL 的完全分析超出了本文范围(请参阅 参考资料 部分获得更多信息)。但是,本例十分简单,可分解如下:

  • jdbc 是 ij 工具与数据库服务器通信的机制。
  • derby 是 JDBC 驱动程序类的名称,ji 工具使用该类与数据库服务器通信。
  • test 是要创建的数据库名称。
  • create=true 是应传递给 Derby JDBC 驱动程序的特定属性。 JDBC 属性列在 URL 其他部分的后面,并用分号分隔。

 

要正确访问,必须将 JDBC URL 作为字符串传递给 connect 命令;因此需要将其封装在单引号 (') 字符里。最后,告诉 ij 工具处理命令,必须添加分号(因为 ji 是 Java 工具)并按下 Return。在短暂的延迟之后,ij 工具提供一个新提示符。那就是 —— 新数据库已创建。

想知道发生了什么,使用 exit 命令(别忘了分号)退出 ij 工具,查看运行 ij 工具的目录(在 UNIX 系统上使用 ls 命令,在 Windows 系统上使用 dir 命令)。这样就生成一个新文件以及一个新目录,叫做 test,它与在 JDBC URL 中为数据库命名的名称相匹配。

如果感到好奇的话,可以研究为您的数据库创建的 test 目录,如 清单 2 所示。(目录的名称和内容可能与这里显示的稍有不同。)


清单 2. test 目录的内容
rb$ ls -CF test/
            log/                    seg0/                   service.properties
            rb$ ls -CF test/log/
            log.ctrl        log1.dat        logmirror.ctrl
            rb$ ls -CF test/seg0/
            c10.dat         c191.dat        c221.dat        c2c1.dat       c90.dat
            c101.dat        c1a1.dat        c230.dat        c2d0.dat       ca1.dat
            c111.dat        c1b1.dat        c241.dat        c2e1.dat       cb1.dat
            c121.dat        c1c0.dat        c251.dat        c2f0.dat       clearcase/" target="_blank" >cc0.dat
            c130.dat        c1d1.dat        c260.dat        c31.dat        cd1.dat
            c141.dat        c1e0.dat        c271.dat        c41.dat        ce1.dat
            c150.dat        c1f1.dat        c281.dat        c51.dat        cf0.dat
            c161.dat        c20.dat         c290.dat        c60.dat
            c171.dat        c200.dat        c2a1.dat        c71.dat
            c180.dat        c211.dat        c2b1.dat        c81.dat
            

研究这些目录时,可能会对创建新目录时发生的所有动作感到吃惊。但要记住,Apache Derby 是 ACID 兼容的数据库,因此,后台发生了好多事情。数据库主目录(本例中为 test)内有一个 log 目录、一个 seg0 目录和一个属性文件。log 目录保存特定于数据库的日志文件,这些文件允许 Derby 记录在一组数据库操作(一个事务)期间发生的操作。如果 Derby 数据库服务器在操作期间由于某种原因终止,则它可以保存停止的位置,并将数据库恢复到正常状态。

在本例中,seg0 目录保存将用于测试数据库的数据文件。很奇怪,所有这些文件都是在数据库刚刚创建时生成的,推测起来应该是空的。原因非常简单:当数据库存储数据时,它不仅创建一个新的文件,还会将数据转储到该文件中。由于性能原因(并满足 ACID 测试),数据库将数据分摊到许多文件中。数据在写入文件时具有特定的结构,称为页面。数据页面的内容包括页面上的数据和有关页面上数据的信息(有时称为元数据)。通过在数据库首次创建时生成所有这些文件(和文件中的页面),数据库可以开始尽快地存储数据。





回页首


ij 工具

ij 工具功能十分强大。可用它(在将来的文章中)执行范围广泛的操作,包括创建数据库(如前所述)和在数据库内创建新项。ij 工具包括一个 help 命令,可以列出和描述要使用的一些常见命令,如 清单 3 所示。注意,为了适应空间限制,该清单已被重新格式化,所以您的版本看起来可能稍有不同。


清单 3. 获得 ij 工具的帮助
rb$ java org.apache.derby.tools.ij
            ij version 10.1
            ij> help ;
            Supported commands include:
            PROTOCOL 'JDBC protocol' [ AS ident ];
            -- sets a default or named protocol
            DRIVER 'class for driver';   -- loads the named class
            CONNECT 'url for database' [ PROTOCOL namedProtocol ]
            [ AS connectionName ];
            -- connects to database URL
            -- and may assign identifier
            SET CONNECTION connectionName; -- switches to the specified
            connection
            SHOW CONNECTIONS;            -- lists all connections
            AUTOCOMMIT [ ON | OFF ];     -- sets autocommit mode for the
            -- connection
            DISCONNECT [ CURRENT | connectionName | ALL ];
            -- drop current, named, or all
            -- connections; the default is CURRENT
            COMMIT;                      -- commits the current transaction
            ROLLBACK;                    -- rolls back the current transaction
            PREPARE name AS 'SQL-J text'; -- prepares the SQL-J text
            EXECUTE { name | 'SQL-J text' } [ USING { name | 'SQL-J text' } ] ;
            -- executes the statement with
            -- parameter values from the USING
            -- result set row
            REMOVE name;                 -- removes the named previously
            -- prepared statement
            RUN 'filename';              -- run commands from the named file
            ELAPSEDTIME [ ON | OFF ];    -- sets elapsed time mode for ij
            MAXIMUMDISPLAYWIDTH integerValue;
            -- sets the maximum display width for
            -- each column to integerValue
            ASYNC name 'SQL-J text';     -- run the command in another thread
            WAIT FOR name;               -- wait for result of ASYNC'd command
            GET [SCROLL INSENSITIVE] CURSOR name AS 'SQL-J query';
            -- gets a cursor (JDBC result set)
            -- on the query
            -- SCROLL cursors are only available
            -- in JDBC 2.0 and higher.
            -- (Cursor scroll type is ignored in
            -- JDBC 1.X.)
            NEXT name;                   -- gets the next row from the
            -- named cursor
            FIRST name;                  -- gets the first row from the
            -- named scroll cursor
            LAST name;                   -- gets the last row from the
            -- named scroll cursor
            PREVIOUS name;               -- gets the previous row from the
            -- named scroll cursor
            ABSOLUTE integer name;       -- positions the named scroll cursor
            -- at the absolute row number
            -- (A negative number denotes
            -- position from the last row.)
            RELATIVE integer name;       -- positions the named scroll cursor
            -- relative to the current row
            -- (integer is number of rows)
            AFTER LAST name;             -- positions the named scroll cursor
            -- after the last row
            BEFORE FIRST name;           -- positions the named scroll cursor
            -- before the first row
            GETCURRENTROWNUMBER name;    -- returns the row number for the
            -- current position of the named
            -- scroll cursor (0 is returned when
            -- the cursor isn't positioned
            -- on a row.)
            CLOSE name;                  -- closes the named cursor
            LOCALIZEDDISPLAY [ ON | OFF ];
            -- controls locale sensitive data
            -- representation
            EXIT;                        -- exits ij
            HELP;                        -- shows this message
            Any unrecognized commands are treated as potential SQL-J commands
            and executed directly.
            ij>
            

清单 3 所示的大多数命令似乎都很陌生,当然啦,您还刚开始学习 Apache Derby。

还可以使用 ij 工具与数据库建立多个连接,如 清单 4 所示。


清单 4. 用 ij 工具建立连接
ij> connect 'jdbc:derby:test;create=true' ;
            WARNING 01J01: Database 'test' not created,
            connection made to existing database instead.
            ij> connect 'jdbc:derby:test' ;
            ij(CONNECTION1)> show connections ;
            CONNECTION0 -   jdbc:derby:test
            CONNECTION1* -  jdbc:derby:test
            * = current connection
            ij(CONNECTION1)> disconnect ;
            ij> show connections ;
            CONNECTION0 -   jdbc:derby:test
            No current connection
            ij> set connection CONNECTION0 ;
            ij> show connections ;
            CONNECTION0* -  jdbc:derby:test
            * = current connection
            ij> exit ;
            

本例首先尝试使用原始的 JDBC URL 连接测试数据库。但是获得一个警告,因为测试数据库已经存在。代码发出一个新 connect 命令以更改 JDBC URL,从而去掉 ;create=true JDBC 属性。这时没有发出警告,但提示符更改为包括一个 (CONNECTION1) 字符串。这看起来不太正常,因为在第一次创建测试数据库时没有发生这种情况。

该结果说明,尽管有警告,但创建数据库连接的第一次尝试成功了。为了展示已经有到同一数据库的两个连接,发出 show connections ; 命令,将显示两个连接、关联的 URL 以及当前连接(在本例为 CONNECTION1)。

现在不需要到同一数据库的两个连接,因此可以使用 disconnect ; 命令关闭当前连接。发出另一个 show connections ; 命令将显示当前惟一打开的连接,但还会看到没有当前连接。因为需要具有活动的或当前的连接向特定数据库发送命令,所以应该相应地更改当前连接。使用 set connections 命令,将目标连接名称作为最终参数,可以容易地实现这一点。现在,发出另一 show connections ; 命令时,将看到当前连接的列表以及当前连接的名称。最后,发出 exit ; 命令断开所有当前连接并终止 ij 工具。





回页首


结束语

本文介绍了关系数据库,并侧重于 ACID 测试。ACID 测试允许开发人员测量数据库系统的利用率。如果需要基于 Java 的轻量级数据库来支持通过 ACID 测试需要的完整能力,则应采用 Apache Derby 数据库。本文还介绍了 Derby 数据库附带的 ij 工具。ij 工具可用于连接数据库并向数据库发出命令。本文使用 ij 工具创建了一个新数据库,然后研究了 Derby 创建新数据库时生成的目录和文件。

查看本系列的下一期文章,将会获得使用模式进行数据库开发的全面概述。

原文转自:http://www.ltesting.net