java Derby 介绍
清单 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”.
?
?
④其他常用命令
除了前面介绍的几种比较重要的命令外,还有一些其他常用的命令,例如关闭数据库连接等,
????????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路径中。
?
?
在这儿,我们碰到了第一个问题。执行这样的代码,并产生100,000(或更多)个domain对象将肯定会导致java用完堆栈空间,产生一个“java.lang.OutOfMemoryError”的错误。对于初学者来说,我们首先必须找到一个方法来使得这个程序工作。
分页Result Sets
随着程序中数据量的增多,你首先想到的应该做的事就是为特定的记录(通常是视图)提供分页支持。正如你在这个介绍性的例子中看到的,简单地去获取庞大的result sets很容易导致 out of memory的错误。
许多数据库服务器支持特定的SQL结构,它们可以用于获得一个查询结果的特定的子集。例如,在MySQL中,提供了LIMIT和OFFSET关键字,它们可以用于select查询。因此,如果你执行类似下面的查询:
?
?
通过这些额外的语句,我们提供了“分页”的功能。尽管所有的结果都从数据库服务器中取出了,但是只有那些我们感兴趣的行才真正的映射到了Java的对象中。现在我们避免了先前碰到的“OutOfMemoryError”的问题了,这样保证了我们的程序可以真正的工作在大的数据表上。
然而,通过这个解决方案,数据库仍然会扫描整个表,然后返回所有的行,这还是一个非常消耗时间的任务。对于我的事例数据库来说,这个操作的执行要花费10秒钟,这在程序中显然是不可接受的。
因此,我们必须给出一个解决方案;我们并不需要返回所有的数据库行,而只需要那些我们感兴趣的(或者至少是所有行的最小可能子集)。我们这儿使用的技巧就是显式的告诉JDBC驱动我们需要多少行。我们可以使用java.sql.Statement接口提供的setMaxRows()函数来完成这个任务。看下面的例子:
?
?
值得注意的是,我们把最大行的值设置为了我们需要的最后一行(增加了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语句来设置该参数。
?
CREATE INDEX tbl_time_create_owner ON tbl(time_create, owner)
?
而不是先前我们使用的索引,我们将不会发现什么性能的优化。那是因为,derby的优化器不认为这个索引是最好的解决方案,从而忽略了它。
索引的缺点
索引可以帮助我们在选择数据的时候改善性能。当然,这也减慢了数据库插入删除以及一些更新操作。因为我们不仅仅有表结构,还有很多的索引结构,所以当数据发生变化时,维护所有的结构是很耗时间的。
例如,当我们在表中插入一行数据的时候,数据库必须更新和这个表的栏有关的所有的索引。这就意味着它必须将一个已索引的栏的数据插入到合适的索引中,这将很花时间。同样的事也会在你删除一个特定的行的时候发生,因为索引必须保证顺序。对于更新操作来说,只有当你更新了已索引的栏的时候受到影响,因为数据库必须重新定位这些索性来保持索引的顺序。
因此,优化数据库和程序设计的关键在于你的需要。不要索引每一个栏,你不一定会要用到这些索引,而且你可能需要优化你的数据库来进行快速的插入。在早期就开始测试数据库的性能并发现瓶颈。只有那时你才该去应用本文中提到的技术。
结论
在本文中,我们研究了一些在日常开发过程中遇到的关于性能的问题。大多数的准则(或进行适当的修改)都可用于任何关系数据库系统。还有很多其他的技术可以帮助你改善你程序的性能。缓存当然是最有效和应用最广泛的方法之一了。对于Java程序员来说,许多的缓存解决方案(部分,如OSCache或者EHCache等开源许可的下的方案)都可以看作是程序和数据库之前的缓存从而提高整个程序的性能。同样,Java项目中用到的许多面向对象的框架(如Hibernate)都拥有内置的缓存能力,所以你应该考虑这些解决方案,不过那是另一个讨论文章的内容了。