其实本人对 derby 并不是特别喜欢,跟 H2 Database 相比,同样都是文件数据库无论是性能上还是程序简洁程度上都略逊一筹。不过现在的项目要用到 derby ,只有把 derby 下载学习一把。
1. 安装
其实从本质上来说 derby 根本就没有真正的安装过程,下载下来直接解压就可以了。以我下载的 db-derby-10.6.2.1-bin.zip 为例。解压后包含以下目录结构 :
bin: 包含 derby 相关的各个运行脚本,有 windows 和 unix 两种版本。
Demo :顾名思义,包含着 derby 自带的各个实例。
Docs: 包括 derby 的所有官网上的文档,分为 pdf 和 html 两种。开始时我还在官网上单独下载文档,原来这个压缩包里已经都自带了。
Javadoc :因为 derby 是完全用 java 语言开发的,这个目录下存放的就是 java 的 API 文档了。
lib: 存放 derby 的 jar 文件。
test: 有 derby 的测试的 jar 包,没用过。
解压完成之后还需要设置一些环境变量。
设置 DERBY_HOME 值为 derby 的安装根目录,另外将 derby 的 bin 目录加入到系统的 PATH 中(均以windows 为例加以介绍的)。
或者启动脚本中进行临时性设置,例如:
这样 derby 就算是安装完成了。
2. 工具的使用
2.1 sysinfo
该命令主要是查看 derby 的版本信息和系统的 Java 信息。启动方式很多,可以直接通过 java 命令启动,因为 derby 本身是 java 编写,所以很多命令都可以通过 java 命令来启动运行,官方文档中有相关介绍。不过我还是习惯上以 derby 自带的脚本的方式运行。以下是我本地运行 sysinfo 的输出结果 :
- F:\studio\derby\DERBYTUTOR>sysinfo
- ------------------ Java 信息 ------------------
- Java 版本: 1.5.0_16
- Java 供应商: Sun Microsystems Inc.
- Java 主目录: D:\Program Files\Java\jdk1.5.0_16\jre
- Java 类路径: D:\Program Files\db-derby-10.6.2.1-bin\lib\derby.
- -derby-10.6.2.1-bin\lib\derbyLocale_zh_CN.jar;D:\Program Files\db-de
- run.jar;D:\Program Files\db-derby-10.6.2.1-bin\lib\derbytools.jar;D:
- -bin/lib/derby.jar;D:\Program Files\db-derby-10.6.2.1-bin/lib/derbyn
- \db-derby-10.6.2.1-bin/lib/derbytools.jar
- OS 名: Windows XP
- OS 体系结构: x86
- OS 版本: 5.1
- Java 用户名: han
- Java 用户主目录:C:\Documents and Settings\User
- Java 用户目录: F:\studio\derby\DERBYTUTOR
- java.specification.name: Java Platform API Specification
- java.specification.version: 1.5
- java.runtime.version: 1.5.0_16-b02
- --------- Derby 信息 --------
- JRE - JDBC: J2SE 5.0 - JDBC 3.0
- [D:\Program Files\db-derby-10.6.2.1-bin\lib\derby.jar] 10.6.2.1 - (9
- [D:\Program Files\db-derby-10.6.2.1-bin\lib\derbytools.jar] 10.6.2.1
- [D:\Program Files\db-derby-10.6.2.1-bin\lib\derbynet.jar] 10.6.2.1 -
- [D:\Program Files\db-derby-10.6.2.1-bin\lib\derbyclient.jar] 10.6.2.
- ------------------------------------------------------
- ----------------- 语言环境信息 -----------------
- 当前语言环境: [中文/中国 [zh_CN]]
- 找到支持的语言环境:[cs]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[de_DE]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[es]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[fr]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[hu]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[it]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[ja_JP]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[ko_KR]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[pl]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[pt_BR]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[ru]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[zh_CN]
- 版本:10.6.2.1 - (999685)
- 找到支持的语言环境:[zh_TW]
- 版本:10.6.2.1 - (999685)
- ------------------------------------------------------
- F:\studio\derby\DERBYTUTOR>
注:上图内容在选取时有部门文字没有选中 。
我觉得当你在一个陌生环境下,首先执行一下这个 sysinfo 命令还是挺有用处的。
2.2 dblook
用于查看数据库中所有部分的结构,包括建表语句等等。
这个命令开始时本人用的脚本的调用方式,一直报错说是 java.sql.SQLException: No suitable driver 。后来才发现系统自带的 dblook 的脚本有些问题,例如调用脚本为:
其中 dblook 在调用 dblook 的类之前会先调用 derby_common.bat , derby_common.bat 中会对参数进行处理,参数变为:
-d 'jdbc:derby://127.0.0.1:9527/firstdb user petl password petl' -verbose
因为可能其他脚本也会用到 derby_common.bat 就没敢修改这段脚本,只能改成用 java 语法来调用(前提是已经将 derby 的几个 jar 添加到 classpath 下面)。
dblook 的相关参数介绍:
-d <sourceDBUrl>: 指定数据库连接的完整 URL
-z <schemaName> :指定 schema
-t <tableOne> <tableTwo> ...: 表名 , 可以列出多个,中间以空格分隔
-append: 以防止覆盖输出文件,生成的 dblook 的日志为追加模式。
-verbose 除了将错误消息打印到日志文件外,
还将其打印到控制台。如果没有指定此选项,错误将只打印到
日志文件。
-o <filename> 指定将生成的 DDL 写入其中的文件名。
如果没有指定,缺省值是控制台。
2.3 ij
感觉 ij 就是 derby 的一个控制台,很强大,也很重要。文档中关于 ij 的内容最多,用到时可以查阅。在这里只说一下我暂时用的到 ij 。
连接数据库:
- $>ij
- ij 版本 10.6
- ij> connect ‘jdbc:derby://localhost:9527/firstdb/firstdb;user=sa;password=derby’;
- ij>
连接之后的操作就相当于一般的数据库控制台一样了。
3. derby 的启动与停止
derby 的启动模式可以分为 Embedded 和 Network 两种模式。 Embedded 模式是 derby 服务与使用 derby 的Application 位于同一个 JVM 中,而 Network 模式为以往比较常见的 client/server 形式, derby 位于服务器上,对外提供 derby 的服务。
3.1 Embeded 模式的启动
3.1.1 通过控制台启停
可以直接通过 ij 命令来启动。例如:
- $>ij
- ij 版本 10.6
- ij> connect ‘jdbc:derby://localhost:9527/firstdb/firstdb;user=sa;password=derby’;
- ij>create table mytab(
- >ID int,
- >Name varchar2(32)
- >);
- 已插入/更新/删除0行
- Ij>
想要停止时只需键入 exit; 直接退出 ij 即可。
3.1.2 程序中启停
启动方式与平时的 jdbc 的连接方式类似,只是需要指定 driver 为:
org.apache.derby.jdbc.EmbeddedDriver
具体启动方式为:
- String driver = "org.apache.derby.jdbc.EmbeddedDriver";
- String connectionURL = "jdbc:derby:firstdb;user=sa;password=derby";
- Class.forName(driver);
- Connection conn = DriverManager.getConnection(connectionURL);
停止的话,可以停止整个 derby 服务,也可以指定要停止的数据库。
- Try{
- DriverManager.getConnection("jdbc:derby:;shutdown=true;user=sa;password=derby");
- } catch (SQLException se) {
- if ( se.getSQLState().equals("XJ015") ) {
- System.out.println(“shutdown normal”);
- }
- }
整个 Derby 服务在关闭时会抛出 XJ015 的错误,关闭 derby 服务中某个库时会抛出 08006 的错误。这两个需要特殊处理一下。
3.2 Network 模式的启停
3.2.1 通过控制台启停
直接运行 bin 目录下的 NetworkServerControl.bat ,但前提是已经设置了 derby 的 jar 到 classpath 。NetworkServerControl 命令的具体用法可以参照命令本身的提示。举例如下:
注:其中 -h 指定主机名,一般情况下位主机 IP ,或者主机名。本例中指定为 0.0.0.0, 表示监听本机所有可用的 IP 或者主机名。
此时就可以网络的形式连接该服务了。以 ij 连接方式举例:
若要停止 derby 服务同样可以通过 NetworkServerControl 完成。如:
3.2.2 程序中连接和停止
在应用程序中通过 jdbc 对 Network 模式的 derby 服务进行连接于 Embedded 模式的类似,所不同的是驱动要改为 : org.apache.derby.jdbc.ClientDriver
连接的 URL 与通过控制台连接时一致。
因为是 Network 模式,所以在程序中一般不用停 derby 服务。
4. 常用操作
接下来介绍一下 derby 数据中的常用操作
4.1 GET/SET 数据库属性
可以通过 Derby 内置的两个存储过程设置和获取数据的相关属性值:
如:
-- 设置数据库的用户 sa ,密码为 derby
-- 获取用户 sa 的密码
4.2 查看数据库中的所有表
可以通过 表 SYS. SYSTABLES 查看数据库中的表信息。
4.3 查看约束
对应的是 SYS. SYSCONSTRAINTS 表。
5. 权限控制
Derby 的权限控制可以分为系统域、数据库域。系统域是针对 derby 引擎全局的用户信息设置。数据库域是针对某个数据库实例的用户信息的设置,存储在该数据库内。系统域和数据库域有相同的用户的话,数据库域的设置会覆盖掉系统域的设置。
5.1 系统域
在系统设置的 derby.system.home 的目录下添加 derby.properties 文件。
注: derby.system.home 需要设置在 java 的启动参数中,用来设置系统的根目录,如果未设置的话则为当前的启动目录。
在其中类似如下内容:
- ##启用用户认证
- derby.connection.requireAuthentication=true
- ##derby的认证模式方式有好几种,BUILTIN,LDAP,或者直接采用自定义的类。
- derby.authentication.provider=BUILTIN
- derby.user.sa=derby
这样就设置了 derby 的启动和访问需要用户认证,并且成功添加了用户 sa ,密码为 derby 。想要在添加别的用户只需要在后面继续追加用户配置。例如增加用户 gest ,则追加
derby.user.gest=123456
启动或者 derby 数据库时需要在参数中加入用户名和密码,例如通过 ij 连接数据库:
5.2 数据库域
Derby 还支持针对数据库级别的用户设置,并且数据库级的用户会覆盖系统级的用户设置。数据库级的用户设置参数与系统级是一样的,所不同的是数据库级设置时采用自带的存储过程SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY 进行属性的设置。例如同样添加上面的用户可以通过如下步骤。
1. 连接数据库 firstdb
2. 执行
- CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(‘derby.connection.requireAuthentication’,’true’);
- CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(‘derby.authentication.provider’,’ BUILTIN’);
- CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(‘derby.user.sa’,’derby’);
这样一个只对数据库实例 firstdb 有效的用户 sa 就设置成功了。如果想删除用户只需设置对应用户的密码为 null即可。
5.3 自定义类
不论是系统级还是数据库的用户设置都可采用三种 PROVIDER ,除了上面咱们用的 BUILTIN 之外还有LDAP 和自定义类。
其中 LDAP 好像是用一种什么服务,这个感兴趣的可以自己 Google 一下。在这里说一下自定义类。自定义类使用时只需设置 derby.authentication.provider 属性值为自定义的完整类名。该类必须实现 derby 的UserAuthenticator 接口。
在这里把官网上的一个简单实现贴一下。因为即使本人在这写一个自己的例子也没有意义,反正具体用的话大家都会根据需求自己开发的。
- import org.apache.derby.authentication.UserAuthenticator;
- import java.io.FileInputStream;
- import java.util.Properties;
- import java.sql.SQLException;
- public class MyAuthenticationSchemeImpl implements
- UserAuthenticator {
- private static final String USERS_CONFIG_FILE = "myUsers.cfg";
- private static Properties usersConfig;
- public MyAuthenticationSchemeImpl() {
- }
- /* static block where we load the users definition from a
- users configuration file.*/
- static {
- FileInputStream in = null;
- usersConfig = new Properties();
- try {
- in = new FileInputStream(USERS_CONFIG_FILE);
- usersConfig.load(in);
- in.close();
- } catch (java.io.IOException ie) {
- // No Config file. Raise error message
- System.err.println(
- "WARNING: Error during Users Config file
- retrieval");
- System.err.println("Exception: " + ie);
- }
- }
- public boolean authenticateUser(String userName,
- String userPassword,
- String databaseName,
- Properties info)
- throws SQLException
- {
- if (userName == null)
- // We do not tolerate 'guest' user for now.
- return false;
- String actualUserPassword;
- actualUserPassword = usersConfig.getProperty(userName);
- if (actualUserPassword == null)
- actualUserPassword = System.getProperty(userName);
- if (actualUserPassword == null)
- // no such passed-in user found
- return false;
- // check if the password matches
- if (!actualUserPassword.equals(userPassword))
- return false;
- // Now, check if the user is a valid user of the database
- if (databaseName != null)
- {
- if (databaseName.equals("DarkSide")) {
- // check if user is a valid one.
- if (!userName.equals("DarthVader"))
- // This user is not a valid one of the passed-in
- return false;
- }
- }
- // The user is a valid one in this database
- return true;
- }
- }
6. Derby 与 hibernate+spring3 整合开发
Derby 与其他数据库在操作上没有什么区别,在这里只是把涉及到的配置文件简单贴出来看一下。
建表语句为
Create table TEST_USER(
ID INT GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1) ,
NAME VARCHAR(32)
);
Spring 配置文件 :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-lazy-init="true">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath*:/application.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value=" org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://127.0.0.1:9527/firstdb" />
<property name="username" value="sa" />
<property name="password" value="derby" />
<property name="initialSize" value="5" />
<property name="maxActive" value="20" />
<property name="maxIdle" value="10" />
<property name="defaultAutoCommit" value="true" />
</bean>
<bean id="sessionFactory" org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.DerbyDialect </prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Hibernate 映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-lazy="false">
<class name="com.harvey.derby.bean.User" table="TEST_USER">
<id name="id"
column="ID"
type="java.lang.Integer"
>
<generator class="native"></generator>
</id>
<property
name="name"
type="java.lang.String"
update="true"
insert="true"
column="name"
/>
</class>
</hibernate-mapping>
关于 derby 的介绍就到这里,说的比较粗枝大叶,具体的还得倒实际用的时候再说吧。