零、回顾
这部分先来回顾一下上两篇博客中的主要内容。第一篇博客中主要简单介绍了Derby数据的历史,特点,安装以及使用的两种模式。第二篇文章主要介绍了客户机-服务器(C/S)模式的使用。今天继续介绍第二种使用模式,内嵌模式(Embedded Mode)。
一、客户端使用内嵌模式
与之前介绍的C/S模式不同,使用内嵌模式时不需要开启一个数据库的服务进程来监听并处理客户端的请求,客户端可以自行的完成这些命令。所以使用内嵌模式是有一定优势的。
下面来具体介绍这种模式的使用。首先还是要设置好CLASSPATH的环境变量。同样有两种方法,即使用Derby数据库编译好的脚本文件。可以执行命令:
setEmbeddedCP
将所需要的jar文件配置在CLASSPATH环境变量中。或者自己手动加入,执行命令:
export CLASSPATH=$DERBY_HOME/lib/derbytools.jar:$DERBY_HOME\lib\derby.jar:
我们还是需要运行ij工具,运行方式可以参照上一篇博客。之后还是执行连接数据库的命令:
jdbc:derby:DB_Path/DB_NAME;create=true'
这里需要多说一句,就是查找数据路径的根目录位置,如果没有设置derby.system.home(即数据库主目录的位置),那么默认的将会从启动ij的当前目录作为主目录对数据库的位置进行递归查找,后面第二部分介绍的程序运行Embedded模式也会遇到相同的问题。这部分先来介绍一下怎么来设置derby.system.home。设置这个时需要在启动ij工具的同时就不值设定好,所以可以执行命令:
java -Dderby.system.home=DB_ROOT_DIR org.apache.derby.tools.ij
上述设置完derby.system.home后再连接数据库会有一个ERROR XBM0H的错误,不知道怎么解决,希望知道的可以指出一下,亦或是我设置derby.system.home的方式有问题,谢谢大家给出问题的解决方案。另外这个模式只能访问本地的数据库,对其操作。连接上数据库后就可以执行SQL语句了,这里就不在赘述了。关闭数据库只须执行exit;即可。
二、程序使用内嵌模式
这里给出的程序是根据Apache Derby文件夹demo/program/sample中的例子改写的,下面附上程序:
package trianlge23.derby.embedded.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class DerbyEmbeddedDemo {
// the default framework is embedded if you want to use client framework
// please pass the "derbyclient" in the first argument
private String framework = "embedded";
private String driver = "org.apache.derby.jdbc.EmbeddedDriver";
private String protocol = "jdbc:derby:";
public static void main(String[] args) {
new DerbyEmbeddedDemo().run(args);
System.out.println("DerbyEmbeddedDemo finished");
}
public void run(String[] args) {
parseArguments(args);
System.out.println("DerbyEmbeddedDemo starting in " + framework
+ " mode");
loaddriver();
Connection conn = null;
ArrayList<Statement> statements = new ArrayList<Statement>();
PreparedStatement psInsert = null;
PreparedStatement psUpdate = null;
Statement s = null;
ResultSet rs = null;
String userHomeDir = System.getProperty("user.home", ".");
String dbPath = userHomeDir + "/Testdata/";
System.setProperty("derby.system.home", dbPath);
String dbName = "testDB";
String dbURL = protocol + dbPath + dbName + ";create=true";
try {
conn = DriverManager.getConnection(dbURL);
conn.setAutoCommit(false);
s = conn.createStatement();
statements.add(s);
s.execute("CREATE TABLE basicinfo(id INT, name VARCHAR(18), cityname VARCHAR(12))");
System.out.println("Created table basicinfo");
psInsert = conn
.prepareStatement("INSERT INTO basicinfo VALUES (?, ?, ?)");
statements.add(psInsert);
psInsert.setInt(1, 100);
psInsert.setString(2, "Triangle23.lzl");
psInsert.setString(3, "Shanghai");
psInsert.executeUpdate();
System.out.println("Inserted 100 Triangle23.lzl Shanghai");
psInsert.setInt(1, 1);
psInsert.setString(2, "Adrastos");
psInsert.setString(3, "Shanghai");
psInsert.executeUpdate();
System.out.println("Inserted 1 Adrastos Shanghai");
psUpdate = conn
.prepareStatement("UPDATE basicinfo SET id=?, name=?, cityname=? WHERE id=?");
statements.add(psUpdate);
psUpdate.setInt(1, 0);
psUpdate.setString(2, "Triangle23");
psUpdate.setString(3, "Beijing");
psUpdate.setInt(4, 100);
psUpdate.executeUpdate();
System.out
.println("Updated 0 Triangle23.lzl Shanghai to 0 Triangle23 Beijing");
rs = s.executeQuery("SELECT * FROM basicinfo ORDER BY id");
int id;
boolean failure = false;
if (!rs.next()) {
failure = true;
reportFailure("No rows in ResultSet");
}
if ((id = rs.getInt(1)) != 0) {
failure = true;
reportFailure("Wrong row returned, expected id=0, got " + id);
}
if (!failure) {
System.out.println("Verified the rows");
}
s.execute("drop table basicinfo");
System.out.println("Dropped table basicinfo");
conn.commit();
System.out.println("Committed the transaction");
if (framework.equals("embedded")) {
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
if (((se.getErrorCode() == 50000) && ("XJ015".equals(se
.getSQLState())))) {
// we got the expected exception
System.out.println("Derby shut down normally");
// Note that for single database shutdown, the expected
// SQL state is "08006", and the error code is 45000.
} else {
System.err.println("Derby did not shut down normally");
printSQLException(se);
}
}
}
} catch (SQLException sqle) {
printSQLException(sqle);
} finally {
// release all open resources to avoid unnecessary memory usage
// ResultSet
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (SQLException sqle) {
printSQLException(sqle);
}
// Remove Statements and PreparedStatements
int i = 0;
while (!statements.isEmpty()) {
// PreparedStatement extend Statement
Statement st = (Statement) statements.remove(i);
try {
if (st != null) {
st.close();
st = null;
}
} catch (SQLException sqle) {
printSQLException(sqle);
}
}
// Close Connection
try {
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException sqle) {
printSQLException(sqle);
}
}
}
private void reportFailure(String message) {
System.err.println("\nData verification failed:");
System.err.println('\t' + message);
}
public static void printSQLException(SQLException e) {
while (e != null) {
System.err.println("\n----- SQLException -----");
System.err.println(" SQL State: " + e.getSQLState());
System.err.println(" Error Code: " + e.getErrorCode());
System.err.println(" Message: " + e.getMessage());
e = e.getNextException();
}
}
private void loaddriver() {
try {
Class.forName(driver).newInstance();
System.out.println("Loaded the appropriate driver");
} catch (InstantiationException ie) {
System.err.println("\nUnable to instantiate the JDBC driver "
+ driver);
ie.printStackTrace(System.err);
} catch (IllegalAccessException iae) {
System.err.println("\nNot allowed to access the JDBC driver "
+ driver);
iae.printStackTrace(System.err);
} catch (ClassNotFoundException cnfe) {
System.err.println("\nUnable to load the JDBC driver " + driver);
System.err.println("Please check your CLASSPATH.");
cnfe.printStackTrace(System.err);
}
}
/* parse arguments choosing client mode whether or not */
private void parseArguments(String[] args) {
if (0 < args.length) {
if ("derbyclient".equalsIgnoreCase(args[0])) {
framework = "derbyclient";
driver = "org.apache.derby.jdbc.ClientDriver";
protocol = "jdbc:derby://localhost:1527/";
}
}
}
}
上述中有程序中有设置derby.system.home的代码段,可以自行体会一下,另外程序给提供了两种模式模式的方式,也算是对之前博客示例的一个追加吧。如果需要查看更完整的注释内容,可以参考Apache给出的示例(之前所述的文件位置)。另外还需要说一点就是,在程序运行时,不能有另一个指向程序所用数据库的服务进程,简单的讲,一个数据库不应该有两个服务进程(不是线程)同时监听请求并处理(不知道解释的对不对啊),内嵌模式是和程序共用jvm的。
三、后面的话
Derby的使用大概就介绍这三篇博客,后续的可能还会有一些derby数据库使用方面的心得。希望这三篇博客可以让大家对使用Derby数据库可以快速上手,也希望大家一起交流给出补充或不足,谢谢。
四、参考资料
- Embedded Derby:http://db.apache.org/derby/papers/DerbyTut/embedded_intro.html
- permission denied on derby.log:
http://apache-database.10148.n7.nabble.com/permission-denied-on-derby-log-td106537.html - Derby 笔记: http://pengyan.iteye.com/blog/207355