
In our previous post “Introduction to Berkeley DB“, the characteristics and functionality of this type of database has already been introduced. This post presents sample code to use a Berkeley DB in a Java program.
Versions of the Berkeley DB Java library
There are two different versions of the Java library for Berkeley DB:
Berkeley DB standard
The package com.sleepycat.db implements an interface to the same system library used by other languages such as C, Perl and PHP. This ensures the compatibility, un such a way that a Berkeley database previously existing, created by a program written in other language, can be used by a Java program, and viceversa.
Berkeley DB Java Edition
The package com.sleepycat.je is a 100% Java implementation. This ensures the portability of databases created with this library among different platforms.
From the programmer’s point of view, the main difference is that in Berkeley DB Java Edition, creating and opening a database has to be done using the class com.sleepycat.je.Environment.
In Berkeley DB standard, using this class is optional.
Other than that, the code used to work with berkeley databases in both libraries is almost identical. It is usually enough to just replace the references to “com.sleepycat.je.*” with “com.sleepycat.db.*” in the import clauses at the top of the source code.
The sample code in this post is written to use Berkeley DB standard.
Installation
It is always possible to install Berkeley DB from scratch, downloading and compiling the source code from the Oracle Berkeley DB download page.
However, there are binary packages available for most platform, making must easier the installation.
For instance, on Debian, Ubuntu, and other linux distros, the installation in done just using apt-get to install the system and java libraries:
1 2 3 |
$ sudo apt-get install libdb-5.1 libdb-java |
once the installation is done, we can check that the java library (that we will need to add to the classpath to compile and run our program) is located under “/usr/share/java”:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ ls -l /usr/share/java/db.jar lrwxrwxrwx 1 root root 13 Jun 28 2012 /usr/share/java/db.jar -> db-5.1.29.jar $ ls -l /usr/share/java/db-5.1.29.jar -rw-r--r-- 1 root root 574871 Jun 28 2012 /usr/share/java/db-5.1.29.jar $ jar tf /usr/share/java/db-5.1.29.jar |more META-INF/ META-INF/MANIFEST.MF com/sleepycat/ com/sleepycat/db/ com/sleepycat/db/Database.class ... |
Creating, opening and closing a database
The following sample code “TestBDB.java” opens a Berkeley database in a file “test.db”.
First, a “Database” object is created with a call to “new Database()”, passing a “dbConfig” argument that specifies the database configuration.
In that configuration, the flag set with the call to “setAllowCreate(true)”, requests that a new database be created, if it does not exist yet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import com.sleepycat.db.DatabaseException; import com.sleepycat.db.Database; import com.sleepycat.db.DatabaseConfig; import java.io.FileNotFoundException; ... Database myDatabase = null; ... try { // Open the database, creating it if it does not exist DatabaseConfig dbConfig = new DatabaseConfig(); dbConfig.setAllowCreate(true); myDatabase = new Database ("test.db", null, dbConfig); } catch (DatabaseException dbe) { // error handling } catch (FileNotFoundException fnfe) { // error handling } |
When all intended accesses to the database have been done, it should be closed. This can be done with the following sample code:
1 2 3 4 5 6 7 8 9 |
try { if (myDatabase != null) { myDatabase.close(); } } catch (DatabaseException dbe) { // error handling } |
The source code in “TestBDB.java”, is compiled and executed with the commands:
1 2 3 4 |
$ javac -classpath /usr/share/java/db.jar TestBDB.java $ java -classpath .:/usr/share/java/db.jar TestBDB |
Writing records to the database
A new record is inserted in the database with a call to the “put()” method in the Database object. The arguments passed to the put() method are two “DatabaseEntry” objects, with the key and the value of the record.
The following code is identical to the code used in Berkely Java Edition, with the only difference of the import clauses at the top, that are importing the classes com.sleepycat.db.* instead of com.sleepycat.je.*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import com.sleepycat.db.Database; import com.sleepycat.db.DatabaseEntry; ... String key = "myKey"; String data = "myData"; try { DatabaseEntry theKey = new DatabaseEntry(key.getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(data.getBytes("UTF-8")); myDatabase.put(null, theKey, theData); } catch (Exception e) { // error handling } |
Reading records from the database
A record is retrieved from the Berkeley database with a call to the “get()” method in the Database object. This method returns an object of class DataEntry, that must be cast into the desired type.
Also in this case, the code is the same as the code used with Berkeley Java Edition, with the only difference of the import clauses:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import com.sleepycat.db.Database; import com.sleepycat.db.DatabaseEntry; import com.sleepycat.db.LockMode; import com.sleepycat.db.OperationStatus; ... String key = "myKey"; try { // Create two objects of class DatabaseEntry // theKey is used to do the search, theData will hold // the value of the given key, if it exists in the database DatabaseEntry theKey = new DatabaseEntry(key.getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(); // call get() to do the search if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) == OperationStatus.SUCCESS) { // cast the value in theData into a String. byte[] retData = theData.getData(); String foundData = new String(retData, "UTF-8"); System.out.println("key: '" + key+ "' value: '" + foundData + "'."); } else { System.out.println("No record found for key: '" + key + "'."); } } catch (Exception e) { // error handling } |
Deleting records
Records are deleted from the database with a call to the “delete” method in the Database object:
1 2 3 4 5 6 7 8 9 10 11 |
try { String key = "myKey"; DatabaseEntry theKey = new DatabaseEntry(key.getBytes("UTF-8")); // Delete the record(s) for the given key myDatabase.delete(null, theKey); } catch (Exception e) { // error handling } |
Process all records in the database
To go through all records in the database, an object of type “Cursor” is created:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import com.sleepycat.db.Cursor; Cursor myCursor = null; try { myCursor = myDatabase.openCursor(null, null); // cursors return every record as a pair of objects of class DatabaseEntry DatabaseEntry foundKey = new DatabaseEntry(); DatabaseEntry foundData = new DatabaseEntry(); // A call to getNext() fetches the next record, until it returns // with a status that is not OperationStatus.SUCCESS while (myCursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) { String keyString = new String(foundKey.getData(), "UTF-8"); String dataString = new String(foundData.getData(), "UTF-8"); System.out.println("Key | Value : " + keyString + " | " + dataString + ""); } } catch (DatabaseException de) { System.err.println("Error accessing the database: " + de); } finally { try { if (myCursor != null) { myCursor.close(); } } catch(DatabaseException dbe) { System.err.println("Error in close: " + dbe.toString()); } } |
References
Getting Started with Berkeley DB
—
Index of posts related to Java programming
—