`
yanguz123
  • 浏览: 553867 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java Derby 介绍

 
阅读更多

 

一、Derby数据库介绍

Apache Derby是一个完美的,100% Java编写的内存数据库,属于Apache的一个开源项目。并且是一个容易管理的关系数据库管理系统,可以和一些商业产品的特性进行交付。

Apache Derby 是一个与平台无关的数据库引擎,它以 Java 类库的形式对外提供服务。

与其他难以部署的数据库不同,Derby数据库体积小、安装非常简单,只需要将其*.jar 文件复制到系统中并为用户的项目添加该*.jar 文件即可。

另外在MyEclipse中集成了Derby数据库的插件应用,并且Derby还提供了Eclipse的插件供开发人员使用。

尽管 Derby 很容易安装,但是它的特性却非常丰富。它可以支持关系数据库中的所有企业级的特性,包括崩溃恢复、事务回滚和提交、行/表级锁、视图、主键/外键约束、触发器、子查询表达式等。一部分的列表特性使Derby从其他的Java 关系数据库管理系统中分离出来,包括: 

         100% Java实现 

         100% Java类型4 JDBC驱动 

         SQL92E标准支持大部分SQL 99特性 

       ACID完全的事务独立的事务支持 

         J2EE支持JNDI,连接池和XA 

         视图,临时表和保存 

         BLOB和CLOB数据类型 

         行和表锁定 

         有价值的基本查询优化 

         服务器端指示约束 

         触发器和存储过程 

         为服务器端函数,触发器或存储过程等操作在数据库里存储Java代码 

         能排除CD-ROM里的只读数据库 

         数据的导入和导出 

         快速数据库加密选项

二、Derby数据库的两种运行模式

1) 内嵌式模式(embedded mode)。Derby数据库与应用程序共享同一个JVM,应用程序会在启动和关闭时分别自动启动或停止关系引擎。Derby包的derby.jar文件包含了Derby 数据库引擎和嵌入式JDBC驱动程序;

2) 网络服务器模式(network server mode)。Derby数据库独占一个JVM,做为服务器上的一个独立进程运行。在这种模式下,允许有多个应用程序来访问同一个Derby数据库。Derby的derbynet.jar文件包含了Derby Network Server。

三、可以从许多技术方面来区分Derby和其他数据库系统

Derby易于管理。当嵌入到客户机应用程序中时,Derby系统不需要任何管理干预。

Derby是可嵌入的。应用程序可以将数据库管理系统(Database Management System,DBMS)引擎嵌入应用程序进程中,从而无需管理单独的数据库进程或服务。

通过网络服务器(Network Server)架构或您选择的服务器架构,可以将Derby作为单独的进程来运行。

Derby是一个纯 Java 的类库:对于 Java 开发人员,这点十分重要,因为他们正试图维护 Java 技术的优点,例如平台无关性、易于配置以及易于安装。

Derby不需要专有的 Java 虚拟机(Java Virtual Machine,JVM)。因为完全是用 Java 语言编写的,所以它适应所有合格的 JVM。

DerbyDBMS 引擎是轻量级的。类文件大小大约是 2MB,并且只使用了 4MB 的 Java 堆。

Derby支持使用 Java 编写存储过程和函数,这些存储过程和函数可以在应用程序的任何层上运行。Derby没有专用的存储过程语言,它使用 JDBC。

四、Derby数据库的优缺点

1、Derby定位是小型数据库, 特别是嵌入式. 支持的数据库小于50GB, 对于小型网站, 事务不复杂的应用, 使用它的还是很不错的. 另外大型桌面应用也可以用它来保存配置和其他数据, 可以做到与文件格式无关, 因为都是访问数据库.

2、功能: Derby支持标准SQL92, SQL1999, SQL2003, 支持临时表, 索引, 触发器, 视图, 存储过程, 外键, 约束, 并行, 事务, 加密与安全等. 只要有JDK(>=1.3), 就可以运行Derby.

3、安全性:Derby的安全性也做得很到位, 包括用户鉴权和加密解密.

4、性能:Derby的性能也是不错的.在插入100万条记录时, CPU的占用率一直低于40%, 平均每插一条记录耗时小于0.3毫秒. 这对于满足桌面应用程序是绰绰有余的. 但是比Oracle、MySql等专业数据库性能要低。

 

 

 

 

 

 

 

1)JDK6包含了一个轻量级的数据库,称为Derby,它属于Apache数据库项目的产品。Derby是基于事务型的关系数据库,在磁盘上占用空间极少。

2)Derby被缺省安装到“安装目录/db”,包含了核心库,示范程序和一个数据库例子。其基本大小仅为2MB。

3)Derby数据库的管理极其简单,它加速了开发和部署的过程,因为其数据库存储是放在JAR文件中的,通过JAR包就发布了。

4)Derby随着JDK6的安装而自动安装。Derby提供了一个命令行工具称为ij,它是交互式JDBC脚本工具的缩写(interactive JDBC scripting tool)。此工具提供了一种方式连接和操纵数据库。

5)要使用Derby,必须在CLASSPATH中包含这个工具,如下:

c:/Program Files/Java/jdk1.6.0/db/derby.jar

c:/Program Files/Java/jdk1.6.0/db/derbytools.jar

在derby.jar文件中包含由JDBC驱动;在derbytools.jar中包含由ij工具。

6)在完成CLASSPATH配置后,要运行ij工具并连接数据库例子,如下:

c:/>java org.apache.derby.tools.ij

ij version 10.2

ij>connect 'jdbc:derby:c:/Program Files/Java/jdk1.6.0/db/demo/databases/toursdb';

ij>

注意:最后的分号不能省略。

7)建立新数据库,如下:

ij>disconnect;  //必须先断开已有数据库的连接

ij>connection 'jdbc:derby:MyDB;create=true';  //必须用创建参数create=true

如上,建立了名为MyDB的数据库。

8)如下的例子,建立数据库,建立表,插入数据,并且浏览它。

ij>create table zipcodes(zipcode varchar(5), city varchar(20), state varchar(2));

0 rows inserted/updated/deleted

ij>insert into zipcodes values('22030','Fairfax','VA');

1 rows inserted/updated/deleted

ij>insert into zipcodes values('22003','Annandale','VA');

1 rows inserted/updated/deleted

ij>insert into zipcodes values('90210','Beverly Hills','CA');

1 rows inserted/updated/deleted

ij>select * from zipcodes;

......

9)Derby中每个数据库的日志记录保存在其下的一个文件中,不管是否有多人对其进行操作。

10)最后以一个例子来结束本题。

用ij执行下面的语句:

connect 'jdbc:derby://localhost:1527/myDB;create=true;user=sa;password=sa';

create table restaurants(id integer, name varchar(20), city varchar(50));

insert into restaurants values (1, 'Irifunes', 'San Mateo');

insert into restaurants values (2, 'Estradas', 'Daly City');

insert into restaurants values (3, 'Prime Rib House', 'San Francisco');

产生一个myDB的数据库和表restaurants;

再用一个java应用程序实现对其的操作:

package myApp;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Properties;

public class DerbyTest {

 public static void main(String[] args) {

  DerbyTest testClient=new DerbyTest();

  testClient.showZipCodes();

 }

 public void showZipCodes(){

  try{

   String driver="org.apache.derby.jdbc.EmbeddedDriver";

   Class.forName(driver).newInstance();

   Connection conn=null;

   conn=DriverManager.getConnection

("jdbc:derby://localhost:1527/myDB;user=sa;password=sa");

   Statement s=conn.createStatement();

   ResultSet rs=s.executeQuery("SELECT * FROM restaurants");

   while(rs.next()){

    System.out.println("序号    :"+rs.getInt(1));

    System.out.println("名字    :"+rs.getString(2));

    System.out.println("城市    :"+rs.getString(3));

    System.out.println();

   }

   rs.close();

   s.close();

   conn.close();

  }catch(Exception e){

   System.out.println("Exception: "+e);

   e.printStackTrace();

  }

 }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Derby 数据库默认启动端口为1527

 

第一篇文章的结尾讨论了如何正确设置系统以使用 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 环境变量的初始化(通过 export 或 set shell 命令)都用两个步骤完成

 

当 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 其他部分的后面,并用分号分隔。

 

help;获得 ij 工具的帮助

现在不需要到同一数据库的两个连接,因此可以使用 disconnect ; 命令关闭当前连接。发出另一个 show connections ; 命令将显示当前惟一打开的连接,但还会看到没有当前连接

 

Derby 风格

这个 文章系列 遵守特定的风格:所有 SQL 命令都用大写,项目名称采用 camelCase 方式,在 camelCase 风格中,单词被连在一起,第一个单词之后的每个单词的第一个字母大写,例如 aLongIdentifier。把这两种风格组合在一起,这些文章写 SQL 命令时的风格是这样:SELECT aLongIdentifier FROM bigdog.dataTable

 

SQL 数据类型

Derby 中的基本整数数据类型(考虑到篇幅和重点的因素这里略下面有地址可以参考下)

 

参考:http://www.ibm.com/developerworks/cn/opensource/os-ad-trifecta3

 

Derby SQL

清单 1. Apache Derby 的 CREATE TABLE 语法

--Comment describing the purpose and layout of the table

 

CREATE TABLE [schemaName.]tableName (

    { <columnDefinition> | <tableLevelConstraint> } [,

        { <columnDefinition> | <tableLevelConstraint> } ) ;

方括号([ 和 ])中的是可选参数。从正式语法中可以看出,模式名是可选的,在必需的头一个列之后(创建连一个列都没有的表是没有意义的),其他列定义或表级约束都是可选的。

 

您可能理解列定义的含义,但是可能不理解约束 的意义。约束有两种类型:表级约束和列约束。约束通过某种方式对列或表进行限制。例如,可以用约束要求列总要有实际的值(没有 NULL 值),或者列中的每个项必须是惟一的,或者列被自动分配默认值。在未来的文章中将更详细地介绍约束。

 

最后一个结束方括号之后的星号(*)代表可以包含一个或多个包含项。这意味着表必须有一个或多个列级或表级约束。竖线(|)表明 “可有可无” 条件。在这个语法示例中,必须定义一个新列或者定义一个表级约束。花括号({ 和 })把相关项组织在一起,而圆括号(( 和 ))中是必需的元素 。最后,分号(;)表示 SQL 语句的结束。

 

用 dblook 查看模式

java org.apache.derby.tools.dblook -d jdbc:derby:test

dblook 工具是一个 Java 类,可以用它方便地把数据库的内容输出到控制台。在命令行上运行它,就像运行其他 Java 程序一样;惟一增加的就是使用 -d jdbc:derby:test 参数,这个参数指定 dblook 工具应当查询的数据库

 

删除 Derby 中的表

DROP TABLE [schemaName.]tableName ;

 

两个破折号 (--) 开头表示是 SQL 注释;您应该使用它们来提供脚本文件中每个主要组件的用途的基本描述

 

ij> run 'derby.create.sql' ;

运行合适的脚本文件,通过使用 run 命令可实现该操作,该命令接受单个参数:单引号括起的脚本文件名当该脚本执行时,您可能会看到新 ij> 提示、命令和警告或错误消息的组合。这种显示可能有些笨拙,但 run 命令会执行您的脚本文件,就像您直接将命令键入 ij 工具中一样

如果正在 Bash shell 中工作,则可以使用 

java org.apache.derby.tools.ij < derby.create.sql > derby.create.out 2> derby.create.err 

实现这一点,它运行 derby.create.sql 脚本文件,将输出消息保存到 derby.create.out 中,并将所有 ij 错误消息保存到 derby.create.err 中。

 

清单 2. SQL INSERT 语法

INSERT INTO table-Name

    [ (Simple-column-Name [ , Simple-column-Name]* ) ]

   Expression Expression 词可以扩展为下列四个不同的结构之一:

单行 VALUES 列表 

多行 VALUES 列表 

SELECT 表达式 

UNION 表达式

 

SQL VALUES 表达式的语法相当简单,(INSERT ....VALUES....) 

清单 3. SQL VALUES 语法     VALUES ( Value {, Value }* )

        [ , ( Value {, Value }* ) ]* |

    VALUES Value [ , Value ]* 该语法首先显示多行格式,然后是单行格式(记住,竖线字符 | 表示或者,星号字符 * 表示一个或多个)。value 词表示想要插入特定列的值。要将数据插入多列,必须将一行的数据括在逗号分隔的括号内

 

对应的也可以用命令行:

java org.apache.derby.tools.ij < derby.insert.sql

 

清单 4. SELECT 语句的形式语法

SELECT [ DISTINCT | ALL ] SelectItem [ , SelectItem ]*

FROM clause

[ WHERE clause ]

[ GROUP BY clause ]

[ HAVING clause ]

 

SELECT 语句的其他部分都是可选的。但是,在构建第一个查询之前,您应该知道 Apache Derby 对 SELECT 语句组件的求值顺序。当 Apache Derby 处理查询时,求值顺序是: 

FROM 子句 

WHERE 子句 

GROUP BY 子句 

HAVING 子句 

SELECT 子句

 

表 1. 基本 SQL 布尔操作符 =       p.price = 29.95 测试任何内置类型是否等于指定值。 

<       p.price < 29.95 测试任何内置类型是否小于指定值。 

>       p.price > 29.95 测试任何内置类型是否大于指定值。 

<=      p.price <= 29.95 测试任何内置类型是否小于等于指定值。 

>=      p.price >= 29.95 测试任何内置类型是否大于等于指定值。 

<>      p.price <> 29.95 测试任何内置类型是否等于指定值。 

IS NULL p.description IS NULL 测试表达式或值是否为 null。 

IS NOT NULL p.description IS NOT NULL 测试表达式或值是否非 null。 

AND    (p.price > 29.92) AND (p.itemNumber > 5) 测试两个表达式是否都为真或者值为非零。 

OR     (p.price > 29.92) OR (p.itemNumber > 5) 测试两个表达式的一个或二者是否为真或值为非零。 

NOT    NOT v.vendorNumber = 1 测试表达式是否为假或值为零。 

BETWEEN p.price BETWEEN 29.95 AND 39.95 测试一个值是否包含于两个其他值之间(示例等价于 29.95 <= p.price <= 39.95)。 

LIKE    v.vendorName LIKE 'Lun%' 测试字符表达式是否与模式相匹配,其中百分比字符 (%) 匹配零个或多个任意字符,下划线字符 (_) 只匹配一个任意字符。

 

清单 5. 使用表连接查询两个表

ij> SELECT p.price, p.description AS "Item", 

        v.vendorName AS "Vendor"

        FROM bigdog.products AS p, bigdog.vendors AS v

        WHERE p.itemNumber = v.itemNumber ;

 

清单 1. 在查询中使用 DISTINCT 限定符

ij> connect 'jdbc:derby:test' ;

ij> SELECT DISTINCT vendorNumber AS "Vendor #" FROM bigdog.vendors ;

清单 2. 在查询中使用 ORDER BY 子句

ij> SELECT v.vendorNumber AS "Vendor #", vendorName as "Vendor",

        p.price as "Price", p.itemNumber AS "Item #"

    FROM bigdog.products AS p, bigdog.vendors AS v

    WHERE p.itemNumber = v.itemNumber AND p.price > 20.0

    ORDER BY v.vendorNumber ASC, p.price DESC ;

 

在查询中执行数学操作

表 1. Apache Derby 数学操作符 一元 +    +1.0   一个空操作,或无操作,如 +4 = 4 

一元 -    -p.price 将值的符号更改为所应用的符号 

+       p.itemNumber + 10 将第二个值加到第一个值上 

-       p.itemNumber - 10 将第一个值减去第二个值 

*       p.price * 1.0825 将第一个值乘以第二个值 

/       p.price / 100.0 将第一个值除以第二个值

 

表 2. Apache Derby 类型转换函数 BIGINT BIGINT(123.45) 返回给定字符串或数字的 64-bit 整数常量。 

CHAR   CHAR(123.45) 返回给定值的固定长度的字符表示,最大长度为 254 个字节,该给定值必须是内置的 Apache Derby 类型之一。可以提供可选的第二个参数以指定字符串的长度。 

DATE   Date('2006-05-16') 返回输入值的日期表示。 

DOUBLE DOUBLE(123.45) 返回输入数字或字符串的双精度浮点表示。 

INTEGER INTEGER(123.45) 返回给定字符串、日期、时间或数字的整数常量。 

SMALLINT SMALLINT(123.45) 返回给定字符串或数字的小整数常量。 

TIME     TIME('12:24:30') 返回输入值的时间表示。 

TIMESTAMP TIMESTAMP('2006-05-16','12:24:30') 返回输入值的时间戳表示。 

VARCHAR VARCHAR(123.45) 返回给定日期、时间、时间戳或字符串值的长度可变的字符表示,最大长度为 32,672 个字节

可以使用 CAST 函数来更改字符串的长度或将一种数据类型转换为另一种,其中包括不受 表 2 中列出的类型转换函数支持的那些数据类型(比如 DECIMAL)。

 

清单 3. 使用 CAST 操作符

ij> SELECT p.price AS "Price", 

        DOUBLE(p.price * 1.0825) AS "Float Total", 

        CAST(p.price * 1.0825 AS DECIMAL(6,2)) AS "Total",

        CAST(p.description AS CHAR(20)) AS "Description"

    FROM bigdog.products AS p 

    WHERE p.price > 21.0 AND p.stockDate < Date('2006-01-21') ; 计算聚合值

表 3. Apache Derby 聚合函数 AVG   AVG(p.price) 返回满足某个表达式的所有行的列的平均值。只能与内置数字数据类型一起使用。返回值的精度由要求值的列的精度来定义。 

COUNT COUNT(p.price) 返回满足某个表达式(比如查询)的行数。可与任何数据类型一起使用。 

MAX   MAX(p.price) 返回满足某个表达式的所有行的列的最大值。只能与内置数据类型一起使用。 

MIN   MIN(p.price) 返回满足某个表达式的所有行的最小值。只能与内置数据类型一起使用。 

SUM   SUM(p.price) 返回满足某个表达式的所有行的列的总和。只能与内置数据类型一起使用。 

清单 4. 在查询中使用聚合函数

ij> SELECT COUNT(p.itemNumber) AS Number, 

        CAST((AVG(p.price) + 0.005) AS DECIMAL(5,2)) AS Average,

        MIN(p.stockDate) AS "First Date", MAX(p.stockDate) AS "Last Date"

    FROM bigdog.products AS p ;

 

数学函数

表 4. Apache Derby 数学函数 ABS or ABSVAL ABS(-1.0) 返回表达式的绝对值,该值必须是内置数值类型之一。返回类型与参数类型相同。 

MOD           MOD(1, 2) 返回第一个参数除以第二个参数时的余数。返回类型与具有最大整数类型(SMALLINT、INTEGER 或 BIGINT)的参数相同。结果符号由第一个参数的符号单独确定。 

SQRT          SQRT(0.5) 返回表达式的平方根,该值必须是浮点值。返回类型与参数类型相同。

 

日期和时间函数

例如,可以将清单 3 所示的查询中 WHERE 子句的 p.stockDate < Date('2006-01-21') 部分替换为 YEAR(p.stockDate) < 2006。

表 5. Apache Derby 日期和时间函数 DAY    DAY(p.stockDate) 返回一个整数,其中包含一个日期、时间戳或包含有效日期的字符串的日期部分 

HOUR   HOUR('12:21:30') 返回一个整数,其中包含一个时间、时间戳或包含有效时间的字符串的小时部分 

MINUTE MINUTE('12:21:30') 返回一个整数,其中包括一个时间、时间戳或包含有效时间的字符串的分钟部分 

MONTH MONTH('2005-12-20') 返回一个整数,其中包括一个日期、时间戳或包含有效日期的字符串的月份部分 

SECOND SECOND('12:21:30') 返回一个整数,其中包括一个时间、时间戳或包含有效时间的字符串的秒钟部分 

YEAR   YEAR(p.stockDate) < 2006 返回一个整数,其中包括一个日期、时间戳或包含有效日期的字符串的年份部分

 

表 6. Apache Derby 字符串函数 ||            (p.description||v.vendorName)      串联操作符将两个值组合为一个新字符串。如果两个值都是 CHAR 类型,结果还是 CHAR类型。如果值为VARCHAR 类型或数值数据类型(可以转换为 VARCHAR 类型),则结果类型是 VARCHAR。 

LCASE 或 LOWER LCASE(p.description) 返回一个字符串,其中输入值中的所有字母字符都转换为小写。 

LENGTH          LENGTH(p.description) 返回输入值中的字符数。非字符数据隐式转换为字符串。 

LOCATE          LOCATE('beach',p.description) 返回一个子字符串在搜索字符串中第一次出现的起始位置,如果没找到子字符串,则返回 0。第一个参数是子字符串,第二个参数是搜索字符串,可选的起始位置可以提供作为第三个参数。 

RTRIM           RTRIM(p.description) 返回一个字符串,其中输入值结尾处的所有空格都被移除。 

LTRIM           LTRIM(p.description) 返回一个字符串,其中输入值开头处的所有空格都被移除。 

SUBSTR          SUBSTR(p.description, 1, 4) 返回 VARCHAR 类型的输入字符串的一部分,在指定位置处开始,一直延续到字符串末尾,或延续到可的第三个参数指定的位置。如果起始位置是正值,则它相对于字符串的开头;如果是负值,则是相对于字符串的末尾。 

UCASE, or UPPER UCASE(p.description) 返回一个字符串,其中输入值中的所有字母字符都已转换为大写。

 

清单 2.DELETE FROM tableName

[WHERE clause] ij> DELETE FROM bigdog.products 

    WHERE description LIKE '%towel%' OR itemNumber <= 3

 

更新数据

清单 3. SQL UPDATE 语句语法

UPDATE tableName

        SET columnName = Value

        [ , columnName = Value} ]*

        [WHERE clause] ij> UPDATE bigdog.products

    SET price = price * 1.25, stockDate = CURRENT_DATE

    WHERE itemNumber = 6 ;

 

表 1. Apache Derby SQL 当前函数 CURRENT_DATE 以合适的 Apache Derby DATE 格式返回当前日期 

CURRENT_ISOLATION 以两字符字符串返回当前事务处理隔离级别,这将在后续文章中详细讨论 

CURRENT_SCHEMA 以最多 128 个字符的字符串返回模式名称,用于限定未限定的数据库对象名称 

CURRENT_TIME 以合适的 Apache Derby TIME 格式返回当前时间 

CURRENT_TIMESTAMP 以合适的 Apache Derby TIMESTAMP 格式返回当前时间戳 

CURRENT_USER 以最多 128 个字符的字符串返回当前用户的授权标识符,如果没有当前用户,则返回 APP

 

清单 5. 使用嵌入式 SELECT 更新行

ij> UPDATE bigdog.products

    SET price = price * 1.10, description = 'NEW: ' || description

    WHERE itemNumber IN 

        ( SELECT v.itemNumber 

          FROM bigdog.products as p, bigdog.vendors as v 

          WHERE p.itemNumber = v.itemNumber AND v.vendorNumber = 3 ) ;

 

表 2. Apache Derby SQL 操作符和表子查询 IN       itemNumber IN(表子查询) 如果表达式的值在表子查询中,则返回 TRUE,该表子查询只能返回单个列。可以包括 NOT 操作符,如 NOT IN,以仅选择不在表查询中的行。 

EXISTS   EXISTS(表子查询) 如果表子查询返回任何行,则返回 TRUE,如果没有选择任何行,则返回 FALSE。这意味着,取决于表子查询选择的行数,将修改所有行或不修改任何行。可以包括 NOT 操作符以反转该规则。 

ALL      itemNumber = ALL(表子查询) 称为量化比较,因为 ALL 关键字修改比较操作符(=、<、>、<=、>= 或 <> 之一),所以仅当对所有行都为真时,结果才为 TRUE。该表子查询可以返回多个行,但它们必须只有一个列。 

ANY      itemNumber = ANY (表子查询) 另一个量化比较,但是在这个查询中,如果它对于任一行为真,则结果为 TRUE。SOME 可以用作 ANY 的同义词。该表子查询可以返回多个行,但它们必须只有一个列。

 

清单 6. 更新表

ij> CREATE TABLE bigdog.newProducts (

    itemNumber INT NOT NULL,

    price DECIMAL(5, 2),

    stockDate DATE,

    count INT NOT NULL DEFAULT 0,

    description VARCHAR(40) 0 rows inserted/updated/deleted

ij> INSERT INTO bigdog.newProducts(itemNumber, price, stockDate, description) 

    SELECT itemNumber, price, stockDate, description FROM bigdog.products ;

5 rows inserted/updated/deleted

ij> DROP TABLE bigdog.products ;

0 rows inserted/updated/deleted

ij> RENAME TABLE bigdog.newProducts TO products ; 

如本例所示,要修改表,在本例中是将一个新列 count 添加到 bigdog.products 表中,首先要创建一个具有需要的正确模式的表。本例需要包括列约束 NOT NULL 使之始终具有有效的值,并通过使用列约束 DEFAULT 0 为 count 列分配默认值 0。注意如何通过将列顺序列出来合并多列约束

 

清单 2. 使用 GROUP BY 和 HAVING 子句的分组结果 ij> SELECT COUNT(p.itemNumber) AS Number, AVG(p.price) AS Average

        FROM bigdog.products AS p, bigdog.vendors AS v

        WHERE p.itemNumber = v.itemNumber

        GROUP BY v.vendorNumber ;

NUMBER     |AVERAGE    6          |31.4633    

2          |39.9500    

2          |23.9500   

 

3 rows selected

ij> SELECT v.vendorNumber, 

        COUNT(p.itemNumber) AS Number, AVG(p.price) AS Average

        FROM bigdog.products AS p, bigdog.vendors AS v

        WHERE p.itemNumber = v.itemNumber

        GROUP BY v.vendorNumber

        HAVING v.vendorNumber > 1 ;

VENDORNUMB&|NUMBER     |AVERAGE    2          |2          |39.9500    

3          |2          |23.9500   

 

2 rows selected

对 NULL 值进行分组

有时,按照查询选择的行包含 NULL 值。在这种情况下,可能想知道在尝试使用包含 NULL 值的列对行进行分组会发生什么情况。答案是很简单的,而且实际上就是想得到的结果,因为 NULL 值不会影响分组结果。

 

好视图无价

清单 3. 使用视图的正式语法

CREATE VIEW schema.viewName

    [ ( columnName1 [, columnName2] * ) ]

AS sqlQuery ;

 

DROP VIEW schema.viewName ;

清单 4. 在 Apache Derby 中创建和删除视图

ij> CREATE VIEW bigdog.vendorList (Name)

    AS SELECT DISTINCT vendorName FROM bigdog.vendors ;

0 rows inserted/updated/deleted

DROP VIEW bigdog.vendorList 用索引加速

清单 6. Apache Derby SQL 索引操作的正式语法

CREATE [UNIQUE] INDEX schema.indexName

ON schema.tableName ( columnName [ ASC | DESC ]

    [ , columnName [ ASC | DESC ]] * ) ;

 

DROP INDEX schema.indexName ; RENAME INDEX indexName TO newIndexName ; 

清单 7. 在 Apache Derby 中使用索引

ij> SET SCHEMA bigdog ;

0 rows inserted/updated/deleted

ij> CREATE INDEX productsIndex ON products(itemNumber) ;

0 rows inserted/updated/deleted

ij> RENAME INDEX productsIndex TO pi ;

0 rows inserted/updated/deleted

ij> DROP INDEX pi ;

0 rows inserted/updated/deleted

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.         该数据库可在IBM和Apache两处下载,cloudscape是derby数据库的商业版本,由IBM赠送与Apache后的称呼。

Apache一方目前版本是Derby 10.1.0.0 alpha (Apr 28, 2005 / SVN 165185)。由于alpha版,而且Derby 10.0.2.2 (Apr 28, 2005 / SVN 165169)版本的数据库提供的附加工具及少,所以我是去IBM网站下载的数据库。

IBM网站目前版本是V10.0.2.0  Build: 30301,提供3种类型的下载,有installer的linux,win32和没有installer一个单一的zip包文件。win32中包括jdk1.4,考虑到我的机器已经被迫安装了n个jdk,故此我下载了单一zip包的cloudscape。IBM下载地址为:http://www-128.ibm.com/developerworks/cn/db2/library/techarticles/dm-0408cline/index.html,需要以自己的mail作为id注册一个用户才能下载。

2.         下载后运行java –jar 10.0-IBM-Cloudscape.jar,出现安装界面,在这里需要指定安装目录,需要注意的是安装目录尽量不要带有空格。

3.         安装完后需要进行一些环境变量的设置,请根据自己的实际情况增加以下环境变量:

数据库安装目录环境变量:

CLOUDSCAPE_INSTALL= D:\IBM\Cloudscape_10.0

classpath中增加:

.;%CLOUDSCAPE_INSTALL%\lib\derby.jar;%CLOUDSCAPE_INSTALL%\lib\derbynet.jar;%CLOUDSCAPE_INSTALL%\lib\derbytools.jar;%CLOUDSCAPE_INSTALL%\lib\db2jcc.jar;%CLOUDSCAPE_INSTALL%\lib\db2jcc_license_c.jar

path中增加:

%CLOUDSCAPE_INSTALL%\frameworks\NetworkServer\bin

4.         现在就可以对数据库进行操作。该数据库提供两种模式的数据库引擎:1. 服务器架构中充当客户机/服务器的引擎。2. 作为可嵌入类库的数据库引擎。在c/s引擎应该比较了解。可嵌入类库的数据库引擎就是和java程序运行在同一JVM中,不需要启动数据库,不需要对数据库进行管理(对这个我也知道个大概,呵呵)。

1.C/S模式下的数据库访问:

打开dos界面,敲入startNetworkServer启动数据库,再打开一个dos界面敲ij以进行数据库管理。

在D:\IBM\Cloudscape_10.0\demo\databases下有一toursDB的demo数据库,我们要连至该数据库我们可以在ij下敲入:connect 'jdbc:derby:net://localhost:1527/"D:\IBM\Cloudscape_10.0\demo\databases\toursDB"'

例如以下我是对数据库的一些简单操作:

--连接数据库:

ij> connect 'jdbc:derby:net://localhost:1527/"D:\IBM\Cloudscape_10.0\demo\databases\toursDB"';

--创建一个名为abc的表:

ij> create table abc (a int, b int);

0 rows inserted/updated/deleted

--往abc表中插入数据,没into还报错,用sybase用习惯了。

ij> insert abc values(1,2);

ERROR 42X01: DB2 SQL error: SQLCODE: -1, SQLSTATE: 42X01, SQLERRMC: Encountered "abc" at line 1, column 8?42X0(?代表一个怪字符,spaces上发布的时候提示“此空间暂时不可用”,没办法只好用?代替啦,发现问题浪费了我十几分钟时间,TNND)

--这次数据进去了

ij> insert into abc values(1,2);

1 row inserted/updated/deleted

--察看刚才插入的数据

ij> select * from abc;

A          |B

-----------------------

1          |2

1 row selected

--断开数据库连接,没有任何信息输出

ij> disconnect;

--退出ij

ij> exit;

注意命令结束符是分号“;”

如果要停止数据库在dos中敲入stopnetworkserver即可。

2.可嵌入类库模式下对DB的访问(该模式下不需要启动数据库,且ij中只能有一个连接操作数据库)

我的toursDB数据库目录为C:\IBM\Cloudscape_10.0\demo\databases下,如果我们DOS界面所在的目录已经在在该目录,则进入ij后直接敲入“connect 'jdbc:derby:toursDB';”就可以连接至数据库,否则得指定数据库所在路径“connect 'jdbc:derby:C:\IBM\Cloudscape_10.0\demo\databases\toursDB';”。下面是我对数据库的一些访问:

ij> connect 'jdbc:derby:toursDB';

ij> select * from cities;

CITY_ID    |CITY_NAME               |COUNTRY                   |AIRPORT                   |LANGUAGE

       |COU&

----------------------------------------------------------------------------------------------------

------------

1          |Amsterdam               |Netherlands               |AMS                       |Dutch

       |NL

……………………………等等

87 rows selected

ij> disconnect;

ij> exit;

C:\IBM\Cloudscape_10.0\demo\databases>

其中cities是toursDB数据库自带的一个表,其它的表还有airlines, countries,flightavailability,flights,flights_history,maps。

关于数据库的一些操作命令可在ij下敲入help;进行察看,详细的帮助信息在D:\IBM\Cloudscape_10.0\doc\pdf中,IBM的developerWorks下的DB2有很多介绍cloudscape相关技术的文章,网址:http://www-128.ibm.com/developerworks/cn/index.html。 还有IBM的在线帮助手册有3本是中文的,网址:http://www.elink.ibmlink.ibm.com/public/applications/publications/cgibin/pbi.cgi?CTY=US&FNC=ICL,进去后选择cloudscape。

 

 

在(一)中提到以嵌入式引擎作为db不是很清楚其工作方式,后来考虑了下大概就是个强大的Access数据库,这种方式下我觉得将它作为Access数据库来进行理解比较直观些。

 

目前我就用了eclipse下访问derby的3个插件:

 

1)        ibm和apache的两个插件一起使用,安装后在java项目点击右键后出现“Apache Derby”,里面有一个菜单“Add Apache Derby nature”,点击后将出现start、ij、sysinfo工具,这个插件就这些东西。

 

2)       用Quantum或dbedit插件访问derby.dbedit插件比较强大些,可以可视的进行表的alert操作,好像没有proc,view的显示界面。Quantum有proc,view的显示界面,但是没法可视进行添加表功能。两个都有可视sql edit界面。我没搞定如何用derby的jdbc进行对数据库的访问,只能用db2的jdbc访问,url为:jdbc:db2://localhost:1527/"C:\IBM\Cloudscape_10.0\demo\databases\toursDB"

 

 

 

 

 

 

 

 

 

 

在Java6中,新增加了Derby数据库,一个轻量级的数据库(Apache Database项目的产品),一个完全基于Java的数据库。相信它的发展应该不错。因为Apache出的产品,一般都表现不错,而且Derby还源于(IBM)CloudSacpe。

 

        使用Derby的好处:磁盘上的数据库比较小,对于基本数据库,大约2MB就够了;较少的管理,并且与Java集成,可以加速开发,同时也便于学习;支持归档在JAR文件中的数据库的存储,使部署变得轻松无比。下面对其基本命令机型简单介绍:

 

使用工具首先需要配置环境变量: JAVA_HOME(Java的安装目录) Path=%Path%;%JAVA_HOME%/bin CLASSPATH=.;%CLASSPATH%;%JAVA_HOME%/db/lib/derby.jar;%JAVA_HOME%/db/lib/derbytools.jar。配置好环境变量后,在命令行模式下,启动Derby的管理工具ij:java org.apache.derby.tools.ij。连接数据库,在ij工具下执行:connect 'jdbc:derby:databaseInstance';即可,举例: connect 'jdbc:derby:D:/tools/jdk1.6.0_03/db/demo/databases/toursdb';新建数据库,举例: connect 'jdbc:derby:D:/tools/jdk1.6.0_03/db/demo/databases/myfirst;create=true'。

查看数据库中已有的表:show tables;查看表结构:describe tableName;

现在很多数据库都支持序列化主键,同样Derby也有类似功能: create table student  (stuId int generated by default as identity (START WITH 2, INCREMENT BY 1), stuName varchar(10)); insert into student values (1, '王五'); insert into student values (DEFAULT, '李四'); insert into student values (DEFAULT, 'salut'); insert into student(stuName) values ('刘七');

在程序中,连接数据库: class.forName("org.apache.derby.jdbc.EbeddedDriver").newInstance(); Connect conn = DriverManager.getConnection("jdbc:derby:derbyInstance");

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1          Derby数据库介绍

Derby是用纯Java写的一个事务、关系数据库,只占用很少的磁盘空间。Derby起源于CloudScape,后者是IBM从Informix获取的产品。在2004年,IBM决定将CloudScape开放源代码,使之成为Apache Software Foundation下的一个孵卵器项目,其名称为Derby。使用Derby的实际好处在于它需要最少的管理以及小的资源占用。磁盘上的数据库比较小,对于基本数据库,大约是2MB。管理最少的事实允许开发人员在代码中轻松地创建和使用数据库。这加速了开发。因为Derby支持归档在JAR文件中的数据库的存储,这使您只需分发JAR文件,因而部署变得如此轻松。

 

从2006年7月13日Java 6 JDK发布起,Derby就默认安装在C:\Program Files\Java\jdk1.6.0\db中,其中包含核心库、示范程序和示例数据库。

2          安装与配置

Derby官方主页:http://db.apache.org/derby/index.html

Derby下载页面:http://db.apache.org/derby/derby_downloads.html

       要安装Derby,你必须先从Derby的网站下载Derby最新版本的zip或者tar包。当前最新版本是db-derby-10.3.2.1-bin 。

发行版本有:

 --二进制发行版包括了代码,示例程序和文档.已经优化了的jar文档在lib目录下

 --lib发行版本包括了优化程序,部署Derby的最小jar的集合.

 --lib-debug发行版本包括了调试Derby和报告问题的有用的最大集合.

 --src发行版本包括了要来产生上面三个发行版的源文件.

 

安装Derby,只要把你下载的包文件解压到你指定的目录即可。

假定你下载的是二进制发行版。

 解压下载的包,之后有以下几个子目录:

 --demo包括了示例程序

 --bin包括了运行和设置环境的代码

 --javadoc包括了有源代码生产的aip文档

 --doc包括了Derby文档

 --lib包括了Derby的jar文件

 

根据Derby手册说明,配置Derby有几种方式:

1. 通过java命令运行安装目录lib相应的工具。

2. 通过运行Derby提供的脚本命令。先配置PATH环境变量指向Derby目录下bin目录,然后运行bin目录内相关批处理命令,即可。

3. 通过运行安装目录lib内的derbyrun.jar归档文件。

要手工通过Java命令运行Derby是很麻烦的,并且也不方便使用。可以将PATH环境变量指向Derby目录下bin目录,这时我们可以在其它地方也能过运行Derby。但是官方提供的相关处理脚本要配置环境变量比较多有点麻烦,需要指定CLASSPATH为:%Derby 安装目录%\lib\derby.jar; %Derby 安装目录%\lib\derbytools.jar; %Derby 安装目录%\lib\derbynet.jar; %Derby 安装目录%\lib\derbyclient.jar;。

为了不想多设置环境变量,我写了个批处理derbyrun.bat文件,只要将path指向该处理文件,就可以在任何地方运行Derby。注意:一定要将该文件放在安装目录bin下或者放在exec(自建目录)\derbyrun.bat

derbyrun.ba内容:

 

@echo off

@rem

@rem Derby Database Run Tools

@rem

@rem

@rem derbyrun.bat ij [-ppropertiesfile] [sql_script]

@rem derbyrun.bat sysinfo [-cp...] [-cp help]

@rem derbyrun.bat dblook [arg]*(or no arguments for usage)

@rem derbyrun.bat server [arg]*(or no arguments for usage)

@rem

 

@rem %~dp0 is expanded pathname of the current script under NT

set DERBY_HOME=%~dp0..

 

@rem echo "%DERBY_HOME%lib\derbyrun.jar"

 

rem Slurp the command line arguments. This loop allows for an unlimited number

rem of arguments (up to the command line limit, anyway).

 

set DERBY_CMD_LINE_ARGS=%1

if ""%1""=="""" goto beginRunCommand

shift

:setupArgs

if ""%1""=="""" goto beginRunCommand

set DERBY_CMD_LINE_ARGS=%DERBY_CMD_LINE_ARGS% %1

shift

goto setupArgs

 

:beginRunCommand

@rem run tools

java -jar "%DERBY_HOME%lib\derbyrun.jar" %DERBY_CMD_LINE_ARGS%

 

 

:end

set DERBY_CMD_LINE_ARGS=

 

运行数据库:

运行:<derbyrun

结果:

D:\temp\Download\db-derby-10.3.2.1-bin\bin<derbyrun

用法:

java -jar derbyrun.jar ij [-p propertiesfile] [sql script]

java -jar derbyrun.jar sysinfo [-cp ...] [-cp help]

java -jar derbyrun.jar dblook [args](或如果调用时没有使用参数,则可执行 jar 文

件将显示用法消息)

java -jar derbyrun.jar server [args](或如果调用时没有使用参数,则可执行 jar 文

件将显示用法消息)

 

注:derbyrun就相当于java -jar derbyrun.jar命令

 

运行:<derbyrun ij

结果:

D:\temp\Download\db-derby-10.3.2.1-bin\bin<derbyrun ij

ij 版本 10.3

ij<

 

然后运行创建数据库MyDBtest:

ij<Connect ‘jdbc:derby:MyDBtest;create=true’

在上面的Url中指定create=true,则创建一个新的数据库。

连接该数据库:

ij< Connect 'jdbc:derby:MyDBtest;';

ij(CONNECTION1)<

 

这时就可以运行相应SQL语句,进行数据库操作。该步骤为单用户嵌入式数据库操作。

 

让Derby运行在服务器模式下:

启动服务器:

Derbyrun server start 同于java -jar derbyrun.jar server start

关闭服务器:

Derbyrun server shutdown 同于java -jar derbyrun.jar server shutdown

 

 

3          使用与相关命令

官方手册文档:http://db.apache.org/derby/manuals/index.html

PDF格式手册:http://download.csdn.net/source/426441 下载

IJ工具支持的命令包括:

 

 PROTOCOL 'JDBC protocol' [ AS ident ];

                              - 设置缺省协议或已命名的协议

 DRIVER 'class for driver';   - 装入已命名的类

 CONNECT 'url for database' [ PROTOCOL namedProtocol ] [ AS connectionNam

                              - 连接至数据库 URL

                              - 可以指定标识

 SET CONNECTION connectionName; - 切换到指定的连接

 SHOW CONNECTIONS;            - 列示所有连接

 AUTOCOMMIT [ ON | OFF ];     - 设置连接的自动落实方式

 DISCONNECT [ CURRENT | connectionName | ALL ];

                              - 删除当前连接、已命名的连接或所有连接;

                              - 缺省值是 CURRENT

 

 SHOW SCHEMAS;                - 在当前数据库中列示所有模式

 SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schema };

                              - 列示表、视图、过程或同义词

 SHOW INDEXES { IN schema | FROM table };

                              - 列示模式中的索引或表的索引

 DESCRIBE name;               - 列示已命名表中的列

 

 COMMIT;                      - 落实当前事务

 ROLLBACK;                    - 回滚当前事务

 

 PREPARE name AS 'SQL-J text'; - 准备 SQL-J 文本

 EXECUTE { name | 'SQL-J text' } [ USING { name | 'SQL-J text' } ] ;

                              - 使用来自 USING 结果集行的

                              - 参数值执行语句

 REMOVE name;                 - 除去已命名的先前预编译语句

 

 RUN 'filename';              - 从命名文件运行命令

 

 ELAPSEDTIME [ ON | OFF ];    - 设置 ij 的耗用时间方式

 MAXIMUMDISPLAYWIDTH integerValue;

                              - 将每列的最大显示宽度设置为

                              - 整数值

 

 ASYNC name 'SQL-J text';     - 在另一个线程中运行命令

 WAIT FOR name;               - 等待 ASYNC'd 命令的结果

 

 GET [SCROLL INSENSITIVE] CURSOR name AS 'SQL-J query';

                              - 在查询中获取游标(JDBC 结果集)

                              - SCROLL 游标仅适用于

                              - JDBC 2.0 和更高版本。

                              -(在 JDBC 1.X. 中忽略游标滚动类型)

 NEXT name;                   - 从已命名的游标获取下一行

 FIRST name;                  - 从已命名的滚动游标获取第一行

 LAST name;                   - 从已命名的滚动游标获取最后一行

 PREVIOUS name;               - 从已命名的滚动游标获取前一行

 ABSOLUTE integer name;       - 在绝对行号上定位已命名的滚动游标

                             -(负数表示从最后一行起算的位置。)

 RELATIVE integer name;       - 相对与当前行定位已命名的滚动游标

                              -(整数是行号)

 AFTER LAST name;             - 将已命名的滚动游标定位于最后一行的后面

 BEFORE FIRST name;           - 将已命名的滚动游标定位于第一行的前面

 GETCURRENTROWNUMBER name;    - 返回已命名的滚动游标当前位置的行号

                              --(当游标的位置不在一个行上时返回 0。)

 CLOSE name;                  -- 关闭已命名的游标

 LOCALIZEDDISPLAY [ ON | OFF ];

                              -- 控制语言环境敏感数据表示法

 

 EXIT;                        -- 退出 ij

 HELP;                        -- 显示此消息

 

SHOW TABLES;                         --查看数据库里的有多少表

 

SYSINFO;                                  --查看系统安装信息

DBLOOK;

和使用其它的数据库一样,首先加载数据库驱动:

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

然后我们创建一个数据库:

Connection conn=DriverManager.getConnection("jdbc.derby.derbyDB;create=true","user","pwd");

在上面的Url中指定create=true,则创建一个新的数据库。

得到连接之后,我们就可以象访问其它数据库一样,进行相关操作了。

Statement st=conn.createStatement();

st.execute("create table test1(id int,name varchar(20));

st.execute("insert into test1 values(1,'sinboy')");

st.execute("inert into test1 values(2,'Tom')");

ResultSet rs=st.executeQuery("select * from test1");

while(rs.next){

   System.out.println("id:"+rs.getInt(1)+" name:"+rs.getString(2));

}

rs.close();

st.close();

conn.commit();

conn.close();

 

最近学习了下Derby整理下学习经验给大家分享下。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Derby数据库是一个纯用Java实现的内存数据库,属于Apache的一个开源项目。由于是用Java实现的,所以可以在任何平台上运行;另外一个特点是体积小,免安装,只需要几个小jar包就可以运行了。

Derby数据库有两种运行模式:

1) 内嵌模式。Derby数据库与应用程序共享同一个JVM,通常由应用程序负责启动和停止,对除启动它的应用程序外的其它应用程序不可见,即其它应用程序不可访问它;

2) 网络模式。Derby数据库独占一个JVM,做为服务器上的一个独立进程运行。在这种模式下,允许有多个应用程序来访问同一个Derby数据库。

在Apache上,Derby有4种发布包,这里以bin发布包为例。bin发布包中含有包含了执行derby数据库工具、设置derby数据库环境的脚本文件、Demo、jar文件等。

1、 安装Derby数据库

只需要从Derby官方网站下载Derby的zip或者tar包,解压就可以了。这里以db-derby-10.4.1.3-bin版本为例,解压后得到以下目录:

1) bin目录,包含了一些工具脚本和设备环境的脚本;

2) demo目录,包含了一些实例程序;

3) docs目录,包含了Derby的文档;

4) javadoc目录,包含了Derby的API文档;

5) lib目录,包含了Derby数据库的jar文件;

6) test目录,Derby的一些测试jar包;

2、 使用Derby脚本

Derby提供了几个脚本来操作Derby数据库,在使用这些脚本前,你必须先设置好Derby的运行环境。

下面的例子都是在命令行下设置环境变量,这些设置都是临时的,如果你新开一个命令行窗口,则需要重新设置一遍,如果想要使环境变量永久生效,可以在我的电脑中进行设置。

首先设置好DERBY_HOME这个环境变量,为DERBY_HOME指定你的derby目录,假如你的derby解压到了E:\ db-derby-10.4.1.3-bin目录下,则可以在命令行中如下设置:

set DERBY_HOME=E:\ db-derby-10.4.1.3-bin

将DERBY_HOME\bin目录添加到PATH环境变量中:

 set path=%DERBY_HOME%\bin;%PATH%

这样可以简化你稍后在命令行中的输入,否则你每次都必须使用脚本的全路径或者你必须到DERBY_HOME\bin目录中才能执行脚本。

最后需要Derby的jar包添加到classpath环境变量中,在DERBY_HOME%\bin目录中提供了几个脚本用于设置classpath,以简化你手工在classpath中添加jar包的麻烦:

1) setEmbeddedCP。当使用内嵌模式来运行Derby时,可以使用该脚本来设置。该脚本将derby.jar和derbytools.jar添加到环境变量中;

2) setNetworkServerCP。当使用网络模式来运行Derby时,用该脚本来设置Derby服务端的classpath变量。该脚本将derbynet.jar添加到环境变量中;

3) setNetworkClientCP。当使用网络模式来运行Derby时,用该脚本来设置Derby客户端的classpath变量。该脚本将derbyclient.jar和derbytools.jar添加到环境变量中。

一般只有当你通过derbyrun.jar来运行Derby工具时才会使用这些脚本。

Derby提供了三个工具脚本:1)sysinfo;2)ij;3)dblook。运行这三个脚本时,如果你没有设置classpath环境变量,这些脚本会自动进行设置。

1) sysinfo

使用sysinfo可以显示你的Java环境信息和Derby的版本信息。使用方法就是在命令行下直接输入:

sysinfo.bat

2) dblook

使用dblook可以将全部或者部分数据库的DDL定义导出到控制台或者文件中。使用方法:

 dblook.bat –d <sourceDBUrl> [Options]

3) ij

使用ij工具来进行数据库交互,执行SQL脚本,如查询、增删改、创建表等等。在命令行下输入:

 ij.bat

即可启动ij工具,然后就可以开始执行SQL脚本了。当要退出ij工具时,在命令行下输入

 exit;

即可。 

3、 使用ij脚本

1) 运行内嵌模式的Derby数据库

在命令行中输入ij.bat后启动ij工具。然后通过如下命令创建数据库,并与数据库创建连接:

 connect ‘jdbc:derby:firstdb;create=true’;

通过connect命令可以与指定数据库创建连接,通过一个JDBC URL来指定与哪个数据库创建连接。ij命令是不区分大小写的。

参数中jdbc:derby是Derby数据库的驱动协议;firstdb是数据库命,由于没有指定路径,数据库将会被创建在当前你命令行下所在的目录下;create=true表示如果数据库不存在,则创建该数据库;“;”是ij命令的终止符。

 当数据库创建成功时,Derby会在当前你命令行下所在的目录下创建一个与数据库命一致(这里是firstdb)的目录,其中存放了数据库的文件。

 与数据库连接上后,就可以开始执行SQL脚本了,如创建一个表格:

 create table firsttable(id int primary key, name varchar(20));

然后插入记录:

 insert into firsttable values(1, ‘Hotpepper’);

也可以执行查询:

 select * from firsttable;

也可以通过run命令来执行sql文件:

 run 'E:\derby\demo\programs\toursdb\ToursDB_schema.sql';

最后通过exit;来退出ij工具。

你可以在当前你命令行下所在的目录中找到一个derby.log的日志文件,derby在其中记录的数据库启动、关闭的信息。

2) 运行网络模式的Derby数据库

这种模式下,需要使用两个控制台窗口,一个用于启动Derby数据库服务端,另一个做为访问Derby数据库的客户端。

可以通过DERBY_HOME\bin目录下的startNetworkServer.bat来启动Derby数据库服务端,只需要在命令行中输入:

startNetworkServer.bat

 数据库就启动了,启动成功会在控制台输出如下信息:

 已使用基本服务器安全策略安装了安全管理程序。

Apache Derby Network Server - 10.4.1.3 - (648739) 已启动并且已准备好 2008-09-06

 00:38:12.540 GMT 时在端口 1527 上接受连接

在另一个控制台使用ij命令访问Derby数据库服务端,在输入ij.bat启动ij工具后,通过如下命令建立与服务端的连接,并创建一个数据库:

connect 'jdbc:derby://localhost:1527/seconddb;create=true';

参数中的数据库命部分和内嵌模式不同,这里使用了“//localhost:1527/”,访问网络模式的URL需要指定服务器的IP地址和端口,其它的就和内嵌模式一样了。

与服务端连接上后,就可以开始执行SQL脚本了,如创建一个表格:

 create table firsttable(id int primary key, name varchar(20));

然后插入记录:

 insert into firsttable values(1, ‘Hotpepper’);

也可以执行查询:

 select * from firsttable;

也可以通过run命令来执行sql文件:

 run 'E:\derby\demo\programs\toursdb\ToursDB_schema.sql';

最后通过exit;来退出ij工具

4、 在Java应用程序中访问Derby数据库

使用Java代码访问Derby数据库与访问其它数据库的区别如下:

1) JDBC驱动的不同;

2) 数据库连接URL的不同;

3) 在访问内嵌模式数据库时,需要显示关闭数据库。

下面分别实例访问内嵌模式和网络模式Derby数据库的代码

1) 访问内嵌模式Derby数据库

String driver = “org.apache.derby.jdbc.EmbeddedDriver”;

String url = “jdbc:derby:firstdb;create=true”;

Connection conn;

try {

 Class.forName(driver);

 conn = DriverManager.getConnection(url);

}catch(Exception e) {

 ……

}finally {

 ……

 DriverManager.getConnection("jdbc:derby:;shutdown=true");

}

建立好连接后,其它的数据操作,如查询、更新数据都和其它数据库一样,这里不详述。有一点需要注意,通过Java应用程序访问内嵌模式Derby数据库时,应用程序有责任需要在程序结束时关闭Derby数据库,如上面代码finally中的

 DriverManager.getConnection("jdbc:derby:;shutdown=true");

shutdown参数用于关闭Derby数据库,如果url中指定了数据库命,则只会关闭指定的数据库,而不会关闭整个Derby数据库。数据库关闭成功时,Derby会抛出一个错误码为XJ015和一个08006的异常表示关闭成功,应用程序可以不处理这两个异常。

2) 访问网络模式Derby数据库

网络模式和内嵌模式的不同出在于:

A. 数据库连接URL的不同;

B. 应用程序退出时无效关闭Derby数据库;

C. 数据库驱动的不同;

String driver = “org.apache.derby.jdbc.ClientDriver”;

String url = “jdbc:derby: //localhost:1527/firstdb;create=true”;

Connection conn;

try {

 Class.forName(driver);

 conn = DriverManager.getConnection(url);

}catch(Exception e) {

 ……

}

由于网络模式下,Derby数据库做为一个独立运行的数据库,可以被多个应用程序所访问,所以应用程序在运行结束时不应该关闭Derby数据库。

5、 使用derbyrun.jar

通过derbyrun.jar也可以使用上面提到的sysinfo、ij、dblook三个脚本的功能,在使用derbyrun.jar前,除了DERBY_HOME环境变量外,你必须显示设置好classpath环境变量,可以通过上面提到的setEmbeddedCP、setNetworkServerCP、setNetworkClientCP几个脚本来设置,具体使用哪个脚本取决于你如何使用Derby数据库。

可以通过java –jar %DERBY_HOME%\lib\ derbyrun.jar来运行derbyrun中的工具:

1) 使用sysinfo。java –jar %DERBY_HOME%\lib\ derbyrun.jar sysinfo

2) 使用ij。java –jar %DERBY_HOME%\lib\ derbyrun.jar ij

3) 使用dblook。java –jar %DERBY_HOME%\lib\ derbyrun.jar dblook

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Apache Derby 是一个完美的, 100% Java 编写的内存数据库,属于 Apache 的一个开源项目。并且是一个容易管理的关系数据库管理系统,可以和一些商业产品的特性进行交付。

 

Apache Derby 是一个与平台无关的数据库引擎,它以 Java 类库的形式对外提供服务。

 

与其他难以部署的数据库不同, Derby 数据库体积小、安装非常简单,只需要将其 *.jar 文件复制到系统中并为用户的项目添加该 *.jar 文件即可。

 

另外在 MyEclipse 中集成了 Derby 数据库的插件应用,并且 Derby 还提供了 Eclipse 的插件供开发人员使用。

 

尽管 Derby 很容易安装,但是它的特性却非常丰富。它可以支持关系数据库中的所有企业级的特性,包括崩溃恢复、事务回滚和提交、行 / 表级锁、视图、主键 / 外键约束、触发器、子查询表达式等。一部分的列表特性使 Derby从其他的 Java 关系数据库管理系统中分离出来,包括: 

         100% Java 实现 

         100% Java 类型 4 JDBC 驱动 

         SQL92E 标准支持大部分 SQL 99 特性 

       ACID 完全的事务独立的事务支持 

         J2EE 支持 JNDI ,连接池和 XA 

         视图,临时表和保存 

         BLOB 和 CLOB 数据类型 

         行和表锁定 

         有价值的基本查询优化 

         服务器端指示约束 

         触发器和存储过程 

         为服务器端函数,触发器或存储过程等操作在数据库里存储 Java 代码 

         能排除 CD-ROM 里的只读数据库 

         数据的导入和导出 

         快速数据库加密选项

 

二、 Derby 数据库的两种运行模式

 

1 ) 内嵌式模式( embedded mode )。 Derby 数据库与应用程序共享同一个 JVM ,应用程序会在启动和关闭时分别自动启动或停止关系引擎。 Derby 包的 derby.jar 文件包含了 Derby 数据库引擎和嵌入式 JDBC 驱动程序;

 

2 ) 网络服务器模式( network server mode )。 Derby 数据库独占一个 JVM ,做为服务器上的一个独立进程运行。在这种模式下,允许有多个应用程序来访问同一个 Derby 数据库。 Derby 的 derbynet.jar 文件包含了 Derby Network Server 。

 

三、可以从许多技术方面来区分 Derby 和其他数据库系统

 

Derby 易于管理。当嵌入到客户机应用程序中时, Derby 系统不需要任何管理干预。

Derby 是可嵌入的。应用程序可以将数据库管理系统( Database Management System , DBMS )引擎嵌入应用程序进程中,从而无需管理单独的数据库进程或服务。

通过网络服务器( Network Server )架构或您选择的服务器架构,可以将 Derby 作为单独的进程来运行。

Derby 是一个纯 Java 的类库:对于 Java 开发人员,这点十分重要,因为他们正试图维护 Java 技术的优点,例如平台无关性、易于配置以及易于安装。

Derby 不需要专有的 Java 虚拟机( Java Virtual Machine , JVM )。因为完全是用 Java 语言编写的,所以它适应所有合格的 JVM 。

DerbyDBMS 引擎是轻量级的。类文件大小大约是 2MB ,并且只使用了 4MB 的 Java 堆。

Derby 支持使用 Java 编写存储过程和函数,这些存储过程和函数可以在应用程序的任何层上运行。 Derby 没有专用的存储过程语言,它使用 JDBC 。

四、 Derby 数据库的优缺点

 

1 、 Derby 定位是小型数据库 , 特别是嵌入式 . 支持的数据库小于 50GB, 对于小型网站 , 事务不复杂的应用 , 使用它的还是很不错的 . 另外大型桌面应用也可以用它来保存配置和其他数据 , 可以做到与文件格式无关 , 因为都是访问数据库 .

 

2 、功能: Derby 支持标准 SQL92, SQL1999, SQL2003, 支持临时表 , 索引 , 触发器 , 视图 , 存储过程 , 外键 , 约束 , 并行 , 事务 , 加密与安全等 . 只要有 JDK(>=1.3), 就可以运行 Derby.

 

3 、安全性: Derby 的安全性也做得很到位 , 包括用户鉴权和加密解密 .

 

4 、性能: Derby 的性能也是不错的 . 在插入 100 万条记录时 , CPU 的占用率一直低于 40%, 平均每插一条记录耗时小于 0.3 毫秒 . 这对于满足桌面应用程序是绰绰有余的 . 但是比 Oracle 、 MySql 等专业数据库性能要低。

 

 

 

 

 

 

 

 

 

 

 

 

Derby这个完全Java开发的开源的数据库也不例外,因此你必须保证它不会成为你程序的一个瓶颈。尽管人们可以在Derby的手册中找到关于这个话题全面的资料,我还是想更详尽的关注一下这些问题,基于我的经验提供一些具体的例子。本文将着重于那些由在大的数据表中选择查询数据而产生的程序性能问题。

 

  你的结果集将包含从第100个结果开始的50行,即使原先的查询返回了100,000行。许多其他的数据库提供商通过不同的结构提供了相似的功能。不幸的是,Derby并没有提供这样的功能,所以你必须继续使用原先的“select * from tbl”查询语句,然后在应用程序中实现一个分页的机制。让我们来看下面的例子:

 

  Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance(); 

  Connection connection = DriverManager.getConnection( 

  "jdbc:derby://localhost:1527/testDb;"); 

  Statement stmt = connection.createStatement(); 

  ResultSet rs = stmt.executeQuery("SELECT * FROM tbl"); 

  ArrayList allResults = new ArrayList(); 

  int i = 0; 

  while (rs.next()) { 

  if (i > 50 && i <= 100) { 

  // O-R mapping code populate your row from result set 

  DomainObject domainObject = populate(rs); 

  allResults.add(modelObject); 

  } 

  i++; 

  } 

  System.out.println("Results Size: " + allResults.size());

  通过这些额外的语句,我们提供了“分页”的功能。尽管所有的结果都从数据库服务器中取出了,但是只有那些我们感兴趣的行才真正的映射到了Java的对象中。现在我们避免了先前碰到的“OutOfMemoryError”的问题了,这样保证了我们的程序可以真正的工作在大的数据表上。

 

  然而,通过这个解决方案,数据库仍然会扫描整个表,然后返回所有的行,这还是一个非常消耗时间的任务。对于我的事例数据库来说,这个操作的执行要花费10秒钟,这在程序中显然是不可接受的。

 

  因此,我们必须给出一个解决方案;我们并不需要返回所有的数据库行,而只需要那些我们感兴趣的(或者至少是所有行的最小可能子集)。我们这儿使用的技巧就是显式的告诉JDBC驱动我们需要多少行。我们可以使用java.sql.Statement接口提供的setMaxRows()函数来完成这个任务。看以下下面的例子:

 

  Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance(); 

  Connection connection = DriverManager.getConnection( 

  "jdbc:derby://localhost:1527/testDb;"); 

  Statement stmt = connection.createStatement(); 

  stmt.setMaxRows(101); 

  ResultSet rs = stmt.executeQuery("SELECT * FROM tbl"); 

  ArrayList allResults = new ArrayList(); 

  int i = 0; 

  while (rs.next()) { 

  if (i > 50 && i <= 100) { 

  // O-R mapping code populate your row from result set 

  DomainObject domainObject = populate(rs); 

  allResults.add(modelObject); 

  } 

  } 

  System.out.println("Results Size: " + allResults.size());

  值得注意的是,我们把最大行的值设置为了我们需要的最后一行(增加了1)。因此,通过这样的解决方案,我们不是仅仅取得了我们想要的50行,而是先获取了100行,然后从中筛选出我们感兴趣的50行。不幸的是,我们没有办法告诉JDBC驱动从一个具体的行开始,因此我们必须说明要显示的记录的最大行数。这就意味着返回最初的一些记录的操作的性能是很好的,但是随着用户浏览的结果的增多,性能也会下降。好消息就是在大多数的情形下,用户不会浏览的太多的记录,他们会在前几条记录重获得他们寻找的行,或者改变查询策略。在我本人的环境中,上述的例子的执行时间从8秒降到了0.8秒。

 

  这是一个描述如何浏览整个表的简单的例子。但是当查询语句中增加了特定的where条件和排序信息时,事情又开始变化了。在接下来的部分里,我将解释为什么这种情况会发生,以后我们如何保证在那些例子中获得可接受的性能。

 

 

 

 

 

 

一、Derby数据库简介

1、Derby的发展史及特性概述

        Derby是一个开源的,100%由Java开发的关系数据库,随着Java平台的普及Derby也收到了

越来越多的关注。Derby的前身是美国IBM公司的ColudScape。2004年4月,IBM公司将

CloudScape的数据库捐献给了Apache软件基金会,并将其更名为Derby,

接着SUN也为Derby捐献了一个团队。不同的是,在JavaSE6.0中,SUN将其命名为JavaDB。

因此,CloudScape、Derby和JavaDB只是该项目在不同时期的不同名称而已。

        一提起关系数据库,总会让人觉得安装烦琐,空间占用很大。然而Derby却不是这样,

不用安装,可以直接使用。同时,附带的Derby也只占用了JavaSE6.0中不到10MB的空间。

千万不要认为Derby的功能会很弱,其全部支持SQL92标准以及许多SQL99的扩展,并且

提供了事务、崩溃恢复、并发连接等大型数据库的特性,管理几十GB的数据时依然轻松自如,

速度很快。

        同时,由于Derby是由纯java开发的,因此也与生俱来具有了java的跨平台性,可以很好地

工作在各种操作系统上。另外,derby不但可以像传统数据库那样以C/S的方式工作,

也支持嵌入式的工作方式。

2、JavaSE 6.0 中derby的目录结构

       默认是安装路径

"lib"目录中的几个jar文件

derby.jar--------包含了一些使用derby数据库时的所必须类,例如derby数据库的JDBC驱动类。

derbytools.jar-提供了一些实用derby数据库的工具,例如用来管理derby数据库的命令行工具。

derbyclient.jar-提供了一些开发derby数据客户端所必须的类,通过使用该jar包中的类,

        可以开发出对网络模式下derby数据库服务器访问的客户端程序。

derbynet.jar----为网络模式下的derby数据库服务器提供支持的类。

二、管理工具ij

        一般情况下每种数据库系统都会提供管理工具,如mysql的命令行客户端,oracle的sql*plus等。

derby也不例外,专门提供了一个功能非常强大的命令行工具----ij。

1、准备工作

        使用该工具之前,首先需要做一些准备工作,主要是将ij工具需要的jar包路劲添加进classpath环境变量,

以及设置一个名称为DERBY_INSTALL的环境变量,步骤如下:

①修改/增加classpath环境变量(我这里是用户环境变量)

       变量名:classpath

       变量值:C:\Program Files\Sun\JavaDB\lib\derbytools.jar;C:\Program Files\Sun\JavaDB\lib\derby.jar

       如果是修改classpath环境变量,不要忘记加分号。

       提示:根据自己机器中java db的安装情况进行设置。

②增加DERBY_INSTALL环境变量

       变量名:DERBY_INSTALL

       变量值:C:\Program Files\Sun\JavaDB

       提示:根据自己机器中java db的安装情况进行设置。

      完成了上述步骤后,就完成了使用ij命令行工具的准备工作。为了验证准备工作成功,

ij能够正常工作,在命令行提示符窗口(cmd)中输入如下命令

      java org.apache.derby.tools.sysinfo

      如果准备工作的设置没有问题,cmd中会显示java系统的很多信息,如下图所示

2、简单使用

        ij是derby自带的一个功能强大的数据库管理工具,可以进行很多数据库管理的操作,包括创建数据库,

启动/关闭数据库,执行SQL脚本等。完成准备工作后,就可以启动并使用ij工具了。

在cmd中输入如下命令启动ij工具,java org.apache.derby.tools.ij运行情况如下图所示:

下面分别介绍几个常用的ij命令,如下所列:

①创建以及连接数据库

使用ij创建以及连接指定数据库命令命令的语法格式如下:

connect 'jdbc:derby:<数据库路径>[;create=True/False]';

        数据库路劲指的是指定数据库在磁盘上存放的位置,例如“E:\roway”。另外,路径也可以使用相对路径,

例如"roway",此路径表示当前执行目录下的roway子目录,若当前执行目录为“E:\”则实景路径为“E:\roway”。

       方括号的内容是可选的,也就是说可以不写,若不写相当于"create=False"。

"create=False"表示仅连接已经存在的数据库,而"create=True"表示若数据库不存在则创建数据库。

       提示:上面介绍的连接和创建数据库的命令,是用于derby的嵌入式工作模式的,

用于网络情况下的命令将在后面介绍。

例如,下面给出了一个在E盘下roway目录中创建数据库的命令

        connect 'jdbc:derby:e:/roway;create=True';

完成了数据库的创建和连接后,就可以使用其他命令或运行SQL脚本对数据库进行操作了。

        说明:第一次不存在数据库的时候使用"create=True"参数来创建并连接数据库,

以后就可以使用"create=False"参数仅连接数据库了。

②运行SQL语句

③运行SQL脚本

       上面介绍了在ij中直接输入执行SQL语句,在操作简单的情况下很好用,如果操作复杂直接进行输入

就很不方便了。因此,ij中还允许用户使用run命令执行指定的SQL脚本,基本命令格式如下:

        run '<SQL脚本文件的路径>';

在文本编辑器中输入如下SQL脚本,并保存为derby.sql脚本文件,例如“E:/derby.sql”.

 

  1. create table students(  
  2.   id  numeric(20),  
  3.   name  varchar(30),  
  4.   age   numeric(6)  
  5. );  
  6. insert into students values(10001,'Aa',10);  
  7. insert into students values(10002,'Bb',20);  
  8. insert into students values(10003,'Cc',30);  
  9. select * from students;  

连接前面创建的数据库,并使用run命令执行"derby.sql"脚本文件,执行情况如下图所示:

 

④其他常用命令

除了前面介绍的几种比较重要的命令外,还有一些其他常用的命令,例如关闭数据库连接等,

        disconnect;-----------------------断开数据库连接

        Exit;---------------------------------退出ij 工具

三、Derby数据库的嵌入式应用

1、嵌入式derby的工作原理

        在嵌入式工作模式中访问derby数据库的java应用程序与derby的数据库引擎工作在同一个JVM中,

不像别的数据库(如oracle)的数据库连接时连接到JVM之外的数据库引擎中。这样做的优点是,

省去了数据库软件的安装、数据源的配置等步骤,随着java应用程序的启动数据库也启动工作,

特别适合进行单机小软件或测试程序的开发。

        但需要注意的是,嵌入式工作模式中应用程序访问数据库的连接是专有的,这就意味着其他

应用程序不可能在同一时刻访问该数据库。

2、嵌入式derby应用的开发步骤

       进行嵌入式derby应用的开发,与通常的JDBC数据库开发并没有很大的区别,基本步骤还是

加载数据库驱动、创建数据库连接、通过连接操作数据库,只是在细节稍有不同。

①加载数据库驱动

    需要连接的是derby数据库,需要加载derby数据库的jdbc驱动类,位于"lib"目录下的derby.jar文件中。

在运行程序时需要将derby.jar文件的路径添加到classpath路径中。

 

[java] view plaincopy
  1. //加载嵌入式derby的JDBC驱动类  
  2. Class.forName("org.apache.derby.jdbc.EmbeddedDriver");  

说明:网络模式derby的jdbc驱动类不是这个,在后面会介绍。

 

②数据库连接字符串

        成功地加载了数据库驱动类之后可以通过连接字符串来获取数据库连接了,

下面给出了连接字符串的基本格式:

        jdbc:derby:<数据库路径>[;create=True/False]

        另外,要注意的是由于介绍的derby工作在嵌入式模式,因此在应用程序退出之前应该关闭数据库。

关闭嵌入式的derby数据库也是使用连接字符串,下面给出了语法格式。

        jdbc:derby:;shutdown=True

 

[java] view plaincopy
  1. //连接指定的derby数据库  
  2. Connection conn = DriverManager.getConnection("jdbc:derby:e:/roway;create=False","","");  
  3. //关闭已经连接的数据库  
  4. DriverManager.getConnection("jdbc:derby:;shutdown=True");  

提示:在关闭数据库成功后,getConnection()方法将抛出异常来进行通知。

 

③操作数据库

        对derby数据库进行操作所采用的代码和访问其他数据库的完全相同,

也是使用通过数据库连接获取的Statement或PreparedStatement来执行指定的SQL语句。

        说明:从上述3个步骤的介绍中额可以看出,以嵌入式方式访问derby数据库与访问其他数据库基本相同,

想把使用其他数据库的应用移植到derby上市非常容易的。

3、使用嵌入式derby的简单案例

       提示:使用嵌入式derby数据库进行开发和使用其他数据库从编写代码的角度没有太大的不同,

但省去了安装与配置数据库的麻烦,这在特定的情况下将非常有用。

四、Derby数据库的网络模式应用

        derby数据库不但可以通过嵌入式模式工作,与其他的数据库相同,也可以工作在网络模式下

同时为多个应用程序服务,处理来自不同JVM的数据库操作请求。

1、网络模式derby的工作原理

        如果使用过其他的一些大型数据库,例如oracle、db2等,那么应该对数据库的网络

工作模式(c/s模式)的原理相当熟悉。

        在这种模式下derby与其他数据库一样作为一个独立的服务器工作在网络上,等待来自其他

java应用程序的连接请求。这种模式中derby可以同时为不同的java应用程序服务,处理来自不同JVM

的数据库操作请求,也就是说同一时刻可以有多个应用程序访问同一个derby数据库。

        说明:当不适合采用嵌入式进行操作时,例如应用程序与数据库不在同一台机器上,

或者数据库需要多用户并发访问时,就可以采用网络模式的的derby。

2、操作网络模式的derby

        接下来介绍如何对网络模式下的derby进行操作,主要包括以网络模式启动derby

以及使用ij工具连接网络模式的derby。

①以网络模式启动derby

        使用网络模式操作derby数据库前,首先要以网络模式启动derby数据库服务器,

下面给出了启动命令的基本格式:

        java org.apache.derby.drda.NetworkServerControl start [-h <host> [-p <port>]]

        NetworkServerControl是系统提供的一个用于启动derby服务器的类,位于derbynet.jar文件中。

因此需要将derbynet.jar文件路径添加到系统的classpath环境变量中。

        方括号中为可选参数,"-h <host>"用来指定主机,"-p <port>"用来指定端口号,

默认的主机为localhost,默认的端口号为1527。

        例如,下面给出了一个启动derby数据库服务器工作在本机1527端口的命令。

        java org.apache.derby.drda.NetworkServerControl start -h localhost -p 1572

        当成功启动derby数据库的网络服务后,可以从网路中的其他机器或本机来对该机器中的derby数据库

进行操作了。需要特别注意的是,在执行网路操作的过程中,cmd窗口不能关闭,一旦关闭则将断开网路服务。

②使用ij工具连接网络模式的derby

        当derby数据库的网路服务启动后,可以使用ij工具进行连接和操作,

下面给出了ij中连接网络模式derby的名称格式。

        connect 'jdbc:derby://<服务器主机地址>:<服务器端口号>/<数据库路径>[;create=True|False]';

        提示:使用上述命令连接derby数据库服务器之前首先需要将derbyclient.jar文件路径添加到系统的

classpath环境变量中,

例如,下面的命令连接上了上面启动的derby数据库服务。

         connect  'jdbc:derby://localhost:1572/E:/roway';

        如果上述命令在ij中成功执行,则与指定数据库的连接成功建立,接着就可以使用各种命令对所连接的

数据库进行操作了。对网络derby数据库进行操作的命令与嵌入式derby完全相同。

3、开发启动derby网络服务的程序

       实际应用中,不但可以通过前面介绍的命令来启动的derby数据库的网路服务,也可以通过自己开发的

java程序来启动derby数据库的网络服务。

       从前面的介绍中可以发现,通过命令启动derby数据库的网络服务需要使用

org.apache.derby.drda.NetworkServerControl类。同样,自己开发程序启动derby数据库的网络服务也需要

使用这个类,有兴趣的可以自行查阅API。

4、使用网络模式derby的简单案例

      客户端连接网络derby服务器需要的JDBC驱动类org.apache.derby.jdbc.ClientDriver

 

 

 

 

 

 

Dejan Bosanac是一个软件开发者,技术顾问和作家。他关注不同技术的集成和互操作,尤其是与Java以及Web开发相关的领域。

数据库在操作少量测试数据和大量数据的时候,表现行为上有很大的差异。通常,在开发过程前期,人们不会关注数据库性能的问题,但是随着时间的发展,人们必须采取一些措施来保证数据库在大量数据的情况下正常工作。

Derby这个完全Java开发的开源的数据库也不例外,因此你必须保证它不会成为你程序的一个瓶颈。尽管人们可以在Derby的手册中找到关于这个话题全面的资料,我还是想更详尽的关注一下这些问题,基于我的经验提供一些具体的例子。本文将着重于那些由在大的数据表中选择查询数据而产生的程序性能问题。

首先,有很多关于调整Derby属性(诸如页面大小和缓存大小等)的技巧。修改这些参数可以在一定程度上调整数据库的性能,但是在通常情况下,更主要的问题来自与你的程序和数据库的设计,因此,我们必须首先关注这些问题,最后再来考虑Derby的属性。

在接下来的段落里,我将介绍一些能够优化程序中有问题部分的技术。但是,和其他性能优化操作一样,我们需要在优化前先测量并确认问题所在。

一个简单的例子

让我们从一个简单的例子开始:假设我们Web程序中拥有一个“search/list”的页面,要处理一个有接近100,000行的表,并且那个表不是很小的(至少有10栏)。用简单的JDBC来写一个例子,这样我们可以专注在数据库和JDBC问题上来。这篇文章中介绍的所有准则对所有的面向对象的映射工具都适用。

为了使得用户能够列出一个大的表,通常使用下面简单的查询语句。

 

 select * from tbl

 

对应的JDBC语句如下:

 

Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection (
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from tbl");
ArrayList allResults = new ArrayList();
while (rs.next()) {
// Object-Relation mapping code to populate your
// object from result set row
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
System.out.println("Results Size: " + allResults.size());

 

在这儿,我们碰到了第一个问题。执行这样的代码,并产生100,000(或更多)个domain对象将肯定会导致java用完堆栈空间,产生一个“java.lang.OutOfMemoryError”的错误。对于初学者来说,我们首先必须找到一个方法来使得这个程序工作。

分页Result Sets

随着程序中数据量的增多,你首先想到的应该做的事就是为特定的记录(通常是视图)提供分页支持。正如你在这个介绍性的例子中看到的,简单地去获取庞大的result sets很容易导致 out of memory的错误。

许多数据库服务器支持特定的SQL结构,它们可以用于获得一个查询结果的特定的子集。例如,在MySQL中,提供了LIMIT和OFFSET关键字,它们可以用于select查询。因此,如果你执行类似下面的查询:

 

select * from tbl LIMIT 50 OFFSET 100 

 

你的结果集将包含从第100个结果开始的50行,即使原先的查询返回了100,000行。许多其他的数据库提供商通过不同的结构提供了相似的功能。不幸的是,Derby并没有提供这样的功能,所以你必须继续使用原先的“select * from tbl”查询语句,然后在应用程序中实现一个分页的机制。让我们来看下面的例子:

 

Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection(
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM tbl");
ArrayList allResults = new ArrayList();
int i = 0;
while (rs.next()) {
if (i > 50 && i <= 100) {
// O-R mapping code populate your row from result set
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
i++;
}
System.out.println("Results Size: " + allResults.size());

 

通过这些额外的语句,我们提供了“分页”的功能。尽管所有的结果都从数据库服务器中取出了,但是只有那些我们感兴趣的行才真正的映射到了Java的对象中。现在我们避免了先前碰到的“OutOfMemoryError”的问题了,这样保证了我们的程序可以真正的工作在大的数据表上。

然而,通过这个解决方案,数据库仍然会扫描整个表,然后返回所有的行,这还是一个非常消耗时间的任务。对于我的事例数据库来说,这个操作的执行要花费10秒钟,这在程序中显然是不可接受的。

因此,我们必须给出一个解决方案;我们并不需要返回所有的数据库行,而只需要那些我们感兴趣的(或者至少是所有行的最小可能子集)。我们这儿使用的技巧就是显式的告诉JDBC驱动我们需要多少行。我们可以使用java.sql.Statement接口提供的setMaxRows()函数来完成这个任务。看下面的例子:

 

Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection(
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
stmt.setMaxRows(101);
ResultSet rs = stmt.executeQuery("SELECT * FROM tbl");
ArrayList allResults = new ArrayList();
int i = 0;
while (rs.next()) {
if (i > 50 && i <= 100) {
// O-R mapping code populate your row from result set
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
}
System.out.println("Results Size: " + allResults.size());

 

值得注意的是,我们把最大行的值设置为了我们需要的最后一行(增加了1)。因此,通过这样的解决方案,我们不是仅仅取得了我们想要的50行,而是先获取了100行,然后从中筛选出我们感兴趣的50行。不幸的是,我们没有办法告诉JDBC驱动从一个具体的行开始,因此我们必须说明要显示的记录的最大行数。这就意味着返回最初的一些记录的操作的性能是很好的,但是随着用户浏览的结果的增多,性能也会下降。好消息就是在大多数的情形下,用户不会浏览的太多的记录,他们会在前几条记录重获得他们寻找的行,或者改变查询策略。在我本人的环境中,上述的例子的执行时间从8秒降到了0.8秒。

这是一个描述如何浏览整个表的简单的例子。但是当查询语句中增加了特定的where条件和排序信息时,事情又开始变化了。在接下来的部分里,我将解释为什么这种情况会发生,以后我们如何保证在那些例子中获得可接受的性能。

 

确保使用索引(避免全表扫描)

索引在数据库设计中是一个非常重要的概念。因为本文所涉及的范围有限,我并不会详细的介绍索引理论。简单来说,索引是特定的数据库结构,能够允许对表中的行进行快速访问。索引通常是在一栏或多栏上创建的,因为他们比整个表小了很多,他们的主要用处就是快速搜索一栏(多栏)中的值。

Derby自动的为主键和外键的栏以及具有唯一性限制的栏创建索引。对于其他任何栏,我们必须显式的创建索引。在接下来的段落中,我们将研究一些例子来介绍索引在什么时候有用以及为什么有用。

但是首先,我们必须做一些准备。在我们开始优化之前,我们需要能够了解我们执行查询操作的时候数据库中发生了什么。Derby提供了derby.language.logQueryPlan这个参数。如果设置了这个参数,Derby将会把所有执行的查询的查询计划(query plan)记录在derby.log这个文件中(这个文件在derby.system.home文件夹中)。我们可以在启动服务器之前通过合适的derby.properties文件或者执行如下的java语句来设置该参数。

 

 System.setProperty("derby.language.logQueryPlan", "true");

 

通过检查查询计划,我们可以观察Derby在查询中是使用了索引还是进行了全表查询,全表查询是一个很耗时间的操作。

既然我们已经设置好了环境,我们可以开始我们的例子了。假设我们先前使用的表 tb1中有一个没有索引的栏叫做owner。因为对查询结果的排序通常是查询性能低下的主要原因,我将介绍所有与排序有关的优化。现在,如果我们希望修改先前的例子来根据这一栏的值来排序我们的结果,我们需要把我们的查询语句改成如下的样子:

 

 SELECT * FROM tbl ORDER BY owner

 

如果我们用这个查询语句代替先前的语句,执行的时间将是先前的好多倍。尽管我们分页(paginated)了所有的结果,并小心的设置了要获取的行数,总的执行时间将会是8秒。

如果我们查看derby.log文件中查询执行计划,我们可以轻易的发现问题:

 

Table Scan ResultSet for TBL at read committed isolation
level using instantaneous share row locking chosen
by the optimizer

 

这意味着Derby为了将记录排序,是在整个表中执行了查找这个操作。那我们可以做些什么来改善这个情况呢?答案很简单,在这一栏上创建一个索引。我们可以通过如下的SQL语句来做这件事:

 

 CREATE INDEX tbl_owner ON tbl(owner)

 

如果我们重复我们先前的例子,我们将得到一个和我们没有做排序前的那个例子相似的结果(在我的机器上是不到1秒)。

同样,如果你现在查询derby.log,你将看到下面的信息(而不是和上面的一样的):

 

Index Scan ResultSet for TBL using index TBL_OWNER
at read committed isolation level using share row locking
chosen by the optimizer

 

这就意味着我们可以确保Derby使用了刚创建的索引来获取合适的行。

使用合适的索引顺序

我们已经看到了索引是如何帮助我们改善了排序某一栏数据时的性能。但是如果我们尝试去反转排序的顺序的时候会发生什么呢?假设我们希望根据owner栏降序分类我们的数据。在这种情况下,我们原先的查询就会变成如下的语句:

 

 SELECT * FROM tbl ORDER BY owner DESC

 

注意,我们增加了DESC这个关键字,该关键字将按降序来排序我们的结果。如果我们执行这个新修改过的查询语句,将会发现整个执行的时间又增加到先前的8-9秒。并且,在日志文件中,你将会发现又是执行了全表扫描。

解决的方法就是为这一栏创建一个降序的索引。对于我们的owner栏,我们执行如下的SQL语句。

 

 CREATE INDEX tbl_owner_desc ON tbl(owner desc)

 

现在我们对这一栏有两个索引了(两个顺序),因此查询性能又恢复到了可接受的范围了。注意查询日志中这一行:

 

Index Scan ResultSet for TBL using index TBL_OWNER_DESC
at read committed isolation level using share row locking
chosen by the optimizer

 

这使我们确信我们使用了新建的索引。因此,如果你经常要对结果进行降序排序的话,你应该考虑创建一个合适的索引来获取更高的性能。

 

 

重建索引

随着时间的流逝,索引记录将产生碎片,这将导致严重的性能下降。例如,如果我们有一个很久以前创建的索引,例如tb1表的time_create栏。

如果我们执行如下的查询:

 

 SELECT * FROM tbl ORDER BY time_create

 

我们得到很差的性能,很大可能是因为我们根本没有一个索引。不过,如果我们看了以下日志,就可以发现问题所在。你会发现我们使用了索引,但是将看到和下面相似的信息。

Number of pages visited=1210

这意味着数据库在索引查询过程中执行了大量的IO操作,这就是这个查询过程的瓶颈所在。

这种情况的解决方法就是重建索引(drop然后重建它)。这将使得索引进行整理碎片,从而节省我们大量的IO操作时间。我们可以通过下面的SQL语句来重建索引:

 

 DROP INDEX tbl_time_createCREATE INDEX tbl_time_create ON tbl(time_create)

 

你将发现执行时间又降到一个可接受的值(1秒以内)。

同样,你在日志文件中将发现如下的行:

Number of pages visited=5

正如你看到的,执行时间明显的下降了是因为数据库执行了很少的IO操作。

因此,通常的规则就是让你的程序定期重建索引。最好是在程序计划任务一个后台的工作来不时的完成这个工作。

多栏索引

到目前为止,我们专注于简单的单栏的索引和简单的查询。创建owner和time_create的单栏索引可以帮助我们进行过滤和排序。即使时下面的查询语句也具有可接受的性能。

 

 SELECT * FROM tbl WHERE owner = 'dejan'AND time_create > '2006-01-01 00:00:00'  ORDER BY time_create

 

但是如果你尝试执行如下的查询:

 

SELECT * FROM tbl WHERE owner = 'dejan' ORDER BY time_create 

 

那又会是一个漫长的执行过程。这是因为数据库为了排序数据需要执行额外的排序步骤。

解决这种类型的查询的办法就是创建一个包含owner和time_create的索引。我们可以通过执行下面的查询来创建索引:

 

CREATE INDEX tbl_owner_time_create ON tbl(owner, time_create)

 

通过使用这个索引,查询的性能将会得到很大的改善。现在,注意下面的分析日志:

Index Scan ResultSet for TBL using index TBL_OWNER_TIME_CREATE
at read committed isolation level using share row locking
chosen by the optimizer

我们通过使用一个便利的索引来使得数据库可以快速的找到已经排好序的数据。

这个例子中值得注意的是,在“create index”语句中的栏的顺序是非常重要的。多栏索引只有通过在创建索引时定义的第一个栏时才是可优化的。因此,如果我们创建了如下的索引:

 

CREATE INDEX tbl_time_create_owner ON tbl(time_create, owner)

 

而不是先前我们使用的索引,我们将不会发现什么性能的优化。那是因为,derby的优化器不认为这个索引是最好的解决方案,从而忽略了它。

索引的缺点

索引可以帮助我们在选择数据的时候改善性能。当然,这也减慢了数据库插入删除以及一些更新操作。因为我们不仅仅有表结构,还有很多的索引结构,所以当数据发生变化时,维护所有的结构是很耗时间的。

例如,当我们在表中插入一行数据的时候,数据库必须更新和这个表的栏有关的所有的索引。这就意味着它必须将一个已索引的栏的数据插入到合适的索引中,这将很花时间。同样的事也会在你删除一个特定的行的时候发生,因为索引必须保证顺序。对于更新操作来说,只有当你更新了已索引的栏的时候受到影响,因为数据库必须重新定位这些索性来保持索引的顺序。

因此,优化数据库和程序设计的关键在于你的需要。不要索引每一个栏,你不一定会要用到这些索引,而且你可能需要优化你的数据库来进行快速的插入。在早期就开始测试数据库的性能并发现瓶颈。只有那时你才该去应用本文中提到的技术。

结论

在本文中,我们研究了一些在日常开发过程中遇到的关于性能的问题。大多数的准则(或进行适当的修改)都可用于任何关系数据库系统。还有很多其他的技术可以帮助你改善你程序的性能。缓存当然是最有效和应用最广泛的方法之一了。对于Java程序员来说,许多的缓存解决方案(部分,如OSCache或者EHCache等开源许可的下的方案)都可以看作是程序和数据库之前的缓存从而提高整个程序的性能。同样,Java项目中用到的许多面向对象的框架(如Hibernate)都拥有内置的缓存能力,所以你应该考虑这些解决方案,不过那是另一个讨论文章的内容了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics