Basic Concepts
While this section is intended for novices, teaching everything about Java or JDBC is beyond its scope. Many excellent books are available and the SUN site (java.sun.com) has helpful on-line tutorials. The goal of this section is to establish basic context based on what the Fortune Server uses.
Java Basics
Which JDK ?
Derby requires a JDK of 1.3 or higher. See the details in the Getting Started section, which also walks through setting your PATH environment variable to include the JDK bin directory.
Set CLASSPATH
The CLASSPATH environment variable tells the Java compiler and interpreter where to find classes. See the details in the Getting Started section.
Compile
The javac binary compiles a Java class. For example, the HelloWorld.java source file below creates a HelloWorld class:
class HelloWorld { public static void main (String[] args) { System.out.println("Hello, World!"); } }
We would compile that class as shown below:
javac HelloWorld.java
Run
The java binary runs a Java class. Given the HelloWorld application we compiled in the previous step, we would run it like this:
$ java HelloWorld Hello, World!
Jar Files
A jar file is a collection of Java classes. You saw the Derby and Jakarta jar files in the Getting Started section and the fortuneServerSql.jar file in the SQL section.
Packages
Packages define a name space for a group of classes, which avoids name collisions. The Derby jar files all use the org.apache.derby package. You'll see soon that the Fortune Server SQL functions use the examples.tutorial.derby package.
JDBC Basics
Derby supports most features in JDBC 2.0 and some in JDBC 3.0 as well. It uses standard features; does not add any nonstandard features.
Connect to Derby Database
Load the embedded Derby driver as shown below:
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
The first connection to a Derby database boots it:
Connection conn = DriverManager.getConnection("jdbc:derby:fortunes");
Boot and create a Derby database like this:
Connection conn = DriverManager.getConnection("jdbc:derby:fortunes2;create=true");
Transactions and Isolation Levels
By default Derby's connection is in auto-commit mode, which is the JDBC standard for newly created connections. You can override that default as shown below:
conn.setAutoCommit(false);
If you turn auto-commit off, don't forget to commit; otherwise, you'll get an invalid transaction state error when you disconnect:
conn.commit();
Isolation protects users from seeing inconsistent data. The greater the isolation, the lower the concurrency. Derby provides a complete thread-safe multi-connection model supporting all four JDBC/SQL isolation levels. Row level locking is used to support these isolation models. The default isolation level is TRANSACTION_READ_COMMITTED, which means that transactions see a snapshot of the database as of the start of the transaction. Setting the level to TRANSACTION_READ_UNCOMMITTED allows transactions to see in-progress changes ("dirty reads"), including changes that could be later rolled back, so it should be used with care.
Shut Down Database Connection
A clean shutdown performs a checkpoint and releases resources. If an embedded application doesn't shut down Derby, a checkpoint won't have been performed and the next connection will be slower because Derby will run its recovery code.
Shut down a specific database like this:
DriverManager.getConnection("jdbc:derby:fortunes;shutdown=true");
Shut down all databases like this:
DriverManager.getConnection("jdbc:derby:;shutdown=true");
A clean shutdown always throws SQL exception XJ015. While disconcerting, it's harmless. Below is the explanation for the behavior from the derby-dev@db.apache.org mail list (msgNo=420 for any who want to read the complete thread):
The issue is that standard JDBC getConnection() method calls (either DriverManager or DataSource) are used to push the shutdown request to Derby. A successful return from these methods would require a Connection object to be returned. It seemed strange to return a connection object to a database or system that was no longer active, what state would the Connection be in, closed? So the decision was made to throw an exception, which I think matches spirit of the JDBC spec. (Null as a return is not supported by the spec). The use of the standard JDBC mechanisms to push the shutdown request means that the request can be passed to Derby by any networked JDBC driver (e.g. DB2 universal driver, RmiJDBC, Weblogic's old Tengah driver) as well as embedded.