javadb在jdbc中的应用

摘要

学习如何在Java桌面应用中部署基于Apache Derby的Java DB。该文章使用住址名册例子来向你演示一个嵌入式数据库Java DB是如何工作的。

 

正文

       Sun Microsystems最近公布发行支持基于100%Java技术的开源数据库Java DB——Apache Derby数据库。Derby之前是以Cloudscape的名字存在并被人使用,它是由Cloudscape、Informix和IBM共同所有。后来,IBM把Derby产品源代码捐赠给Apache基金会作为一个开源项目。Sun、IBM 其他企业和个人作为Apache Derby社区的一部分也积极参与该关系数据库的开发。Java DB遍布在Sun许多产品中,包括Sun Java Enterprise System和Sun Java System Application Server。NetBeans集成开发环境(IDE) 5.0也支持Java DB。

       Java DB是一个只有2MB的轻量级数据库,并可嵌入到Java技术的桌面应用中。目前桌面应用可以访问带有触发器、存储过程和支持SQL语句的强大数据库存储器,Java Database Connectivity(JDBC)和Java Platform, Enterprise Edition(Java EE,以前称为J2EE),都嵌入了同样的Java虚拟机(JVM)。(见脚注)

       这篇文章描述了如何下载、安装、集成和在桌面应用中部署Java DB。住址名册这个例子将演示一个嵌入式数据库Java DB是如何工作的。

 

内容

-创建住址名册示例

-安装Java DB

-在NetBeans IDE 5.0里集成Java DB

-装载数据库驱动

-连接Java DB数据库

-创建数据库

-使用数据库

-发布你的应用程序

-概要

 

创建住址名册示例

       住址名册示例使用Java DB来存储地址信息。这个示例存储名字、电话号码、email地址和邮政地址。它答应你建立一个新地址条目并可以存储、编辑和删除它们。这个应用程序在用户的主目录下名为.addressbook的子目录下创建它的数据库。这个数据库嵌入在应用程序中的,所以这里不需要设立和治理一个分开的服务器或系统。要发布这个嵌入式数据库应用程序,我们仅仅需要应用程序JAR文件和数据库类JAR文件。插图1展示该示例的用户界面(UI)。

 

在桌面应用中使用JAVA DB(图一)

插图1:住址名册使用嵌入式的数据库Java DB

       住址名册的主框架窗口是AddressFrame类,它继续于Java Foundation Classes/Swing(JFC/Swing)JFrame。AddressFrame类是一个放置其他图形组件的容器,同时也担当控制和处理子组件产生的不同事件。这些子组件是JPanel的子类,每个都有不同的职责:

l         AddressPanel显示地址记录。它也提供编辑存在的记录和创建新记录的UI。它包含显示Address对象的所有主要属性的文本域。

l         AddressActionPanel设置该程序所需的按钮。AddressFrame必须处理这个面板所产生的事件。例如:当用户点击Save按钮,这个面板产生一个事件。AddressFrame监听并处理这个面板的所有重要事件。

l         AddressListPanel设定一个带滚动条的列表来列出名册姓名,显示在AddressFrame的左边。这个列表控制一个ListEntry对象。ListEntry存储数据库记录的唯一标识。这个记录标识(ID)答应应用程序找到该记录的全部信息并显示在AddressPanel上。

该应用程序是用Data Access Object(DAO)去分离数据库特定的代码。DAO封装了数据库connections和statements。一个DAO是一个有益的设计模式,它答应在应用程序和持久化存储机制之间的松耦合。应用程序的AddressDao类是一个DAO的例子。当AddressFrame编辑、保存或修改Address对象时,它总是使用一个AddressDao类的实例。虽然住址名册应用程序使用的是Java DB,你也可以改变它,并使用一个完全不同的数据库,仅仅需要修改这个类而已。

 

安装Java DB

       获取Java DB最简单的方法就是从Sun Developer Network的Java DB站点去下载。二进制版本文件包提供你编写嵌入式数据库应用程序所需要的文件。当你下载完该文件后,你将得到Java DB目录结构,它包含下面一些子目录:

l         Demo子目录有两个示例程序。一个例子显示如何创建一个普通的嵌入式应用。另一个例子则显示如何在客户端-服务器环境下使用Java DB。

l         Frameworks子目录包含的功能有环境变量设置和建立和启动数据库。对于住址名册的示例,这个类是没有用的,因为我们的应用程序将是完全独立的。没有外部的功能被使用。

l         Javadoc子目录包含API文档。这个目录非常有用的,当你配置你的IDE时,都要指明Java DB API javadoc的位置。

l         Docs子目录包含关于Java DB产品的一些文档:安装、治理和参考指南。

 

l         最后,lib子目录包含Java DB库打包成的JAR文件。阅读Java DB文档可以找到不同的库。对于一个嵌入式数据库应用程序,我们们只需要derby.jar库文件。

安装Java DB只需要在你的应用程序环境变量里加入derby.jar文件。它是如此的简单。你可以在你的Solaris,Linux,Windows里设置环境变量,或者在其他主环境里导入这个JAR文件,或者你可以在编译和运行的时候通过命令行参数导入这个文件。假如你使用ANT,住址名册示例的ANT脚本将告诉你在发布工程时如何导入这些JAR文件。另外,某些IDE,包括NetBeans IDE 5.0,答应你设置工程的环境变量。

 

在NetBeans IDE 5.0里集成Java DB

       大多数IDE都提供了添加库文件到开发环境的方法。下面将指导你如何在NetBean IDE5.0里添加Java DB库文件:

1.       在Tools菜单里选择库治理器,如插图2。

在桌面应用中使用JAVA DB(图二)

插图2:库治理器答应你添加第三方库文件到你的工程里

2.       在库治理器窗口,创建一个名为JavaDBEmbedded的新库,如插图3。点击OK。

在桌面应用中使用JAVA DB(图三)

插图3:设置你工程需要的库的名字

3.       添加derby.jar文件到JavaDBEmbedded库,在库治理器窗口里点击Add JAR/Folder…。通过文件选择框选择derby.jar文件。如插图4。

在桌面应用中使用JAVA DB(图四)

插图4:添加derby.jar文件到JavaDBEmbedded库

4.       在同样的库治理器窗口的JavaDBEmbedded库里,选择Javadoc标签。从你安装的Java DB目录里添加javadoc子目录。现在,当你在NetBeans IDE工程里使用JavaDBEmbedded库时,就可用的Java DB API javadoc。

 

 

你现在可以使用工程的属性设置来为NetBeans IDE 5.0工程添加JavaDBEmbedded库文件。当你在IDE下编译,调试和运行该应用程序时,IDE将能找到所需要的derby.jar文件。

为了适用用户使用其他的IDE,我将derby.jar文件放在提供下载的地址名册工程的lib子目录里。也附带了只使用NetBeans IDE就能直接构建和运行该示例的ANT脚本。

 

装载数据库驱动

       装载JDBC技术驱动启动数据库治理系统。Java DB的驱动来自于derby.jar文件,因此你不需要再下载任何东西。装载JDBC驱动通过引用Class.forName方法。嵌入式驱动名是org.apache.derby.jdbc.EmbeddedDriver,你也可以使用其他的JDBC驱动装载它。

 

Class.forName("org.apache.derby.jdbc.EmbeddedDriver");

 

       地址名册示例从配置属性文件里读取驱动名,并传递该名字到loadDriver方法。另外,之前提到的,地址名册封装所有的数据库功能到Data Access Object(DAO),core Java EE design pattern习惯访问数据从多样的来源。在Java SE应用程序中,就像地址名册一样,DAO模式工作得相当好。下面的代码片段表示AddressDao文件如何读取驱动名和装载驱动:

 

private Properties bProperties = null;

 

public AddressDao(String addressBookName) {

    this.dbName = addressBookName;

    setDBSystemDir();

    dbProperties = loadDBProperties();

    String driverName = dbProperties.getProperty("derby.driver");

    loadDatabaseDriver(driverName);

 

    ...

}

 

private Properties loadDBProperties() {

    InputStream dbPropInputStream = null;

    dbPropInputStream =

        AddressDao.class.getResourceAsStream("Configuration.properties");

    dbProperties = new Properties();

    try {

        dbProperties.load(dbPropInputStream);

    } catch (IOException ex) {

        ex.printStackTrace();

    }

 

    return dbProperties;

}

 

private void loadDatabaseDriver(String driverName) {

    // Load the Java DB driver.

    try {

        Class.forName(driverName);

    } catch (ClassNotFoundException ex) {

        ex.printStackTrace();

    }

 

连接Java DB数据库

       JDBC技术连接定义一个独立的数据库并答应你执行治理任务。任务包括启动,停止,复制,甚至删除数据库。驱动治理器提供所有数据库连接。从驱动治理器获得一个连接,倘若定义了URL字符串和一组属性值,将改变数据库连接的交互性。一个非常普通的方法是在连接时关联用户名和密码属性。

       所有连接的URL都使用下面的格式:

 

jdbc:derby:<dbName>[propertyList]

 

 

       dbName是定义一个独立数据库的URL。一个数据库可以有一个或多个位置:在当前工作目录里,在classpath里,在JAR文件里,在一个独有的Java DB数据库主目录里,或者是你的文件系统里的绝对位置。治理数据库位置的最简单方法是在你嵌入式环境里设置derby.system.home系统属性。这个属性告诉Java DB里所有数据库的默认主位置。通过设置这些属性,地址名册示例确保Java DB总是能找到正确的应用程序数据库。应用程序数据库名字为DefaultAddressBook,它将存在于derby.system.home属性所指示的目录里。连接该数据库的URL应该像这样:

 

jdbc:derby:DefaultAddressBook

 

可选值propertyList是一组属性,你可以传递给数据库系统。你可以传递属性到Java DB系统,要么是URL它本身,或是是分开的属性对象。假如属性是URL的一部分,应该用分号来隔开每个属性值。最常用的属性是:

 

l         create=true

l         databaseName=nameOfDatabase

l         user=username

l         passWord=userPassword

l         shutdown=true

 

       要连接DefaultAddressBook数据库,该示例必须首先设置derby.system.home系统属性。该示例使用的是用户主目录的.addressbook子目录。使用System类去找到用户的主目录。然后使用该类来设置derby.system.home属性:

 

private void setDBSystemDir() {

    // Decide on the db system Directory: <userhome>/.addressbook/

    String userHomeDir = System.getProperty("user.home", ".");

 

    String systemDir = userHomeDir + "/.addressbook";

 

    // Set the db system directory.

    System.setProperty("derby.system.home", systemDir);

}

 

一旦应用程序有了明确的指示,所有的数据库都将存在,它可以获得一个数据库连接。在这个例子里,注重,我添加了连接属性到数据库URL。

 

Connection dbConnection = null;

String strUrl = "jdbc:derby:DefaultAddressBook;user=dbuser;password=dbuserpwd";

try {

    dbConnection = DriverManager.getConnection(strUrl);

} catch (SQLException sqle) {

    sqle.printStackTrace();

}

 

       或者,你可以把这些属性放在Properties对象里。当获取连接时,使用这个Properties对象做参数:

 

 

Connection dbConnection = null;

String strUrl = "jdbc:derby:DefaultAddressBook";

 

Properties props = new Properties();

props.put("user", "dbuser");

props.put("password", "dbuserpwd");

try {

    dbConnection = DriverManager.getConnection(strUrl, props);

} catch(SQLException sqle) {

    sqle.printStackTrace();

}

 

创建数据库

       地址名册示例应用程序没有现成的数据库。换句话说,当该应用程序启动时,必须创建数据库。在这个应用程序中使用嵌入式数据库最大的好处是不需要用户关心数据库设置的细节。应用程序可以控制数据库存在的地方,存在那些表和如何进行处理。

       地址名册创建了一个名为DefaultAddressBook的数据库,在用户主目录的一个子目录里,它不会告诉用户任何附加的信息。当获得一个数据库连接后,通过使用create=true属性,你可以在Java DB里创建一个新的数据库。由于我们的数据库将使用DefaultAddressBook数据库,我们首先应该创建这个数据库。假设我们在之前讨论时已经设置了derby.system.home属性值,应用程序创建数据库和连接如下:

 

 

Connection dbConnection = null;

String strUrl = "jdbc:derby:DefaultAddressBook;create=true";

 

try {

    dbConnection = DriverManager.getConnection(strUrl);

} catch (SQLException ex) {

    ex.printStackTrace();

}

 

       因为create=true属性值被包含在里面,Java DB首先会尝试创建数据库文件。创建数据库并不是实际创建任何应用表。然而,你应该能在你的主目录下找到一个名为.addressbook/DefaultAddressBook的子目录。

       在数据库被创建后,应用程序将创建表。该示例仅使用一个ADDRESS表在默认应用程序APP计划。下面是创建ADDRESS表的SQL代码:

 

CREATE table APP.ADDRESS (

    ID          INTEGER NOT NULL

                PRIMARY KEY GENERATED ALWAYS AS IDENTITY

 

                (START WITH 1, INCREMENT BY 1),

    LASTNAME    VARCHAR(30),

    FIRSTNAME   VARCHAR(30),

    MIDDLENAME  VARCHAR(30),

    PHONE       VARCHAR(20),

    EMAIL       VARCHAR(30),

    ADDRESS1    VARCHAR(30),

    ADDRESS2    VARCHAR(30),

    CITY        VARCHAR(30),

    STATE       VARCHAR(30),

    POSTALCODE  VARCHAR(20),

    COUNTRY     VARCHAR(30) )

       每个记录有一个记录标识或ID域。Java DB为每条新记录产生这些值,它将添加到数据。在每条地址记录的ID域是一个要害值。

 

       其他的地址记录域都是不同长度的varchar类型。例如,LASTNAME域能容纳最大30个varchar字符。Varchar类型等价于UTF-16 Java char类型。

       Java技术编码使用下面的代码用上面的SQL语句去创建ADDRESS表。dbConnection是与先前提到的代码相同的。我们把它传递到createTable方法中,创建一个新的Statement,并在新建的数据库里调用execute方法运行SQL代码。strCreateAddressTable实例变量保存SQL语句文本。

 

private boolean createTables(Connection dbConnection) {

    boolean bCreatedTables = false;

    Statement statement = null;

    try {

        statement = dbConnection.createStatement();

        statement.execute(strCreateAddressTable);

        bCreatedTables = true;

    } catch (SQLException ex) {

        ex.printStackTrace();

    }

   

 

    return bCreatedTables;

}

 

       现在,数据库和ADDRESS表都存在于主目录下名为.addressbook/DefaultAddressBook子目录里。虽然你可以浏览这个子目录,避免修改任何文件。假如你直接编辑或删除这些数据库文件,你就破坏了你数据库的完整性。

 

使用数据库

       一旦数据库和它的表被创建,你的应用程序可以创建一个新的连接和声明去增加,编辑,删除,或获得记录。在地址名册中,这些响应是由AddressActionPanel里的按钮所控制。插图5显示了这几个可选项。

l         New.创建一个新的地址记录

l         Delete.删除当前显示的地址记录

l         Edit.编辑当前的地址记录

l         Save.保存新的和编辑过的地址记录

l         Cancel.取消任何编辑或任何尝试新建的记录

在桌面应用中使用JAVA DB(图五)

插图5:地址名册有几个按钮与记录交互

       应用程序的主窗口是AddressFrame,它同时担当控制和显示。它用AddressActionPanel注册它自己去接收通知,当用户点击响应区的按钮时。

       New按钮清除地址条目面版,并答应用户去编辑所有文本框。这里没有使用SQL命令,不过UI应该答应你登录一个新地址。

       Delete按钮尝试删除当前选种的地址记录。AddressFrame从AddressPanel获取当前选择的Address标识,并使用AddressDao删除该记录。该面板调用它自己的deleteAddress方法。该方法用正确的ID做参数调用DAO的deleteRecord方法。在删除数据库记录后,应用程序必须删除AddressListPanel的ListEntry。

 

 

private void deleteAddress() {

    int id = addressPanel.getId();

    if (id != -1) {

        db.deleteRecord(id);

        int selectedIndex = addressListPanel.deleteSelectedEntry();

        ...

    }

    ...

}

 

       在AddressDao里,deleteRecord方式实际上是从数据库删除一条记录。当第一次创建数据库连接时,AddressDao就创建了一个PreparedStatement。

 

stmtDeleteAddress = dbConnection.prepareStatement(

        "DELETE FROM APP.ADDRESS " +

        "WHERE ID = ?");

 

 

       PreparedStatement可以使用多次,每次只需要一个参数就能确定删除哪条记录。在设置了ID参数后,deleteRecord方法执行Update。

 

public boolean deleteRecord(int id) {

    boolean bDeleted = false;

    try {

        stmtDeleteAddress.clearParameters();

        stmtDeleteAddress.setInt(1, id);

        stmtDeleteAddress.executeUpdate();

        bDeleted = true;

    } catch (SQLException sqle) {

        sqle.printStackTrace();

    }  

    return bDeleted;

}

 

 

       Edit按钮答应用户在AddressPanel里编辑当前选择的Address记录。在这个例子中,你可以修改记录的名字,城市或电话号码。

       Save按钮要么是在AddressPanel里创建和编辑新的Address,要么就尝试编辑更新存在的记录。假如用户是编辑一个记录。Save按钮将使用新的信息来更新记录。假如用户是创建一个新的记录,Save按钮将插入一个新的记录到数据库。新的还没有被保存。这时,它的ID域仍然设置的是默认值-1。一旦你保存这条记录,这个值是自动生成的,并成为该记录的唯一标识。

       下面是AddresFrame里的代码是通过调用DAO的editRecord或saveRecord方法来保存编辑后或新建的地址记录。当然,当你创建一条新记录,应用程序也必须更新AddressListPanel。

 

private void saveAddress() {

    if (addressPanel.isEditable()) {

        Address address = addressPanel.getAddress();

        int id = address.getId();

        if (id == -1) {

            id = db.saveRecord(address);

            address.setId(id);

            String lname = address.getLastName();

            String fname = address.getFirstName();

 

            String mname = address.getMiddleName();

 

            ListEntry entry = new ListEntry(lname, fname, mname, id);

            addressListPanel.addListEntry(entry);

         } else {

            db.editRecord(address);

        }

        addressPanel.setEditable(false);

    }

}

 

       DAO的editRecord方法必须更新Address记录里更改的域。由于该应用程序示例不能分辨修改和未修改的域,它就更新了记录的所有域。下面是PreparedStatement对象和editRecord方法:

stmtUpdateExistingRecord = dbConnection.prepareStatement(

    "UPDATE APP.ADDRESS " +

 

    "SET LASTNAME = ?, " +

    "    FIRSTNAME = ?, " +

    "    MIDDLENAME = ?, " +

    "    PHONE = ?, " +

    "    EMAIL = ?, " +

    "    ADDRESS1 = ?, " +

    "    ADDRESS2 = ?, " +

    "    CITY = ?, " +

    "    STATE = ?, " +

    "    POSTALCODE = ?, " +

    "    COUNTRY = ? " +

    "WHERE ID = ?");

   

 

    ...

 

public boolean editRecord(Address record) {

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值