一、Berkeley DB Java Edition简介
- Berkeley DB JE is a general-purpose, transactionally protected, embedded database written in 100% Java (JE makes no JNI calls). As such, it offers the Java developer safe and efficient in-process storage and management of arbitrary data.
- Berkeley DB的特点:
- 数据存储能力很强(Large database support)
- 支持多线程(Multiple thread and process support)
- 数据库的记录很简单,只是简单的键值对(Database records)
- 提供事务支持(Transactions)
- 提供索引支持(Indexes)
- 提供内存缓存的支持(In-memory cache)
- 按照连续的记录文件存储数据(Log files)
- 后台线程的支持(Background threads)
- 数据库环境封装了一个或多个数据库(Database environments)
- 支持数据库的备份和恢复(Backup and restore)
- 下载Berkeley DB Java Edition:可以从http://www.sleepycat.com/download/index.shtml网址下载
- 安装Berkeley DB Java Edition:将下载的文件解压后放到JE_HOME下面。
- 使用Berkeley DB,应用程序使用时,需要配置je.jar包,要将JE_HOME/lib/je.jar 加到你的应用程序中
- Berkeley DB Exception主要有三个异常:DatabaseNotFoundException,DeadlockException,RunRecoveryException
二、Berkeley DB Java Edition的使用及举例说明
根据Berkeley DB的文档介绍,在这里简单的介绍一下用Berkeley DB开发的步骤:
- 构建数据库的开发环境
用Berkeley DB Java Edition开发数据库时,需要构建数据库的开发环境。Berkeley DB主要是在这个环境下工作的,并且处理数据库也是在这个环境下工作的。
import com.sleepycat.je.Environment; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.EnvironmentConfig; import java.io.File; ...... Environment myDbEnvironment = null; try { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); /**这里的"/export/dbEnv"就是指定的数据库开发环境的目录*/ myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig); } catch (DatabaseException dbe) { // Exception handling goes here } |
在这里对环境的属性可以进行设置,当然也可以通过配置文件je.properties来得到。
像上例中的"envConfig.setAllowCreate(true);"这个设置就是说,当设置为true时,说明若没有数据库的环境时,可以打开。否则就不能打开。其它的属性,可以查看有关Berkeley DB Java Edition文档。
程序运行完了,一般要关闭数据库的环境的,这就需要调用myDbEnvironment.close()方法来执行,释放系统资源。
- 构建数据库
数据库的构造是在数据库环境的基础上构建的,这里还需要数据库属性的配置,不同的数据库可以配置不同的属性设置。
例:
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import java.io.File;
......
Environment myDbEnvironment = null;
Database myDatabase = null;
......
try {
// Open the environment. Create it if it does not already exist.
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
// Open the database. Create it if it does not already exist.
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
myDatabase = myDbEnvironment.openDatabase(null,
"sampleDatabase",
dbConfig);
} catch (DatabaseException dbe) {
// Exception handling goes here
}
|
从这里的例子可以看出数据库myDatabase需要DatabaseConfig的配置,一般数据库的属性的配置需要它在这里的配置,然后数据库myDatabase才可以得到。如:myDatabase = myDbEnvironment.openDatabase(null,"sampleDatabase",dbConfig);
这里的“dbConfig.setAllowCreate(true);”就是设置数据的是否可以创建的属性,这里是可以创建的。有关数据库配置的其它属性,可以查看有关的文档。
释放数据库资源一般用Database.close()来操作。
- 使用数据库的字段
Berkeley DB中的记录包括两个字段,就是键和值,并且这些键和值都必须是com.sleepycat.je.DatabaseEntry类的实例。
import com.sleepycat.je.DatabaseEntry;
......
String aKey = "key";
String aData = "data";
try {
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
} catch (Exception e) {
// Exception handling goes here
}
|
在这里可以看到,我们用的是UTF-8的编码,其实,也可以使用其它的编码。对于存储和得到数据都不会产生任何影响。
当得到从数据库中得到数据时,因为它都是按照字节存储的,所以,我们取出数据时,需要转换一下。
import com.sleepycat.je.DatabaseEntry; ...... byte[] myKey = theKey.getData(); byte[] myData = theData.getData(); String key = new String(myKey); String data = new String(myData); ...... 这样就可以按照Java中的String类,来取出数据了。 |
- 对数据库的各种操作具有了数据库对象之后,就可以根据这个数据库对象来执行具体的数据库操作,包括插入,检索,删除的操作。
在Berkeley DB中默认是不支持重复记录的,若有重复的记录集的话,也可以使用游标来完成操作。
- 从数据库中插入数据:这里提供了三种方法,put(),putNoOverwrite(),putNoDupData(),它们的主要区别还是在于插入的记录是否有重复,根据重复记录来判断这些操作,多数情况下,使用put()方法来操作插入。
import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.Database; ..... String aKey = "myFirstKey"; String aData = "myFirstData"; try { DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8")); DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8")); myDatabase.put(null, theKey, theData); } catch (Exception e) { // Exception handling goes here } |
- 从数据库中取得数据,一般使用get()方法得到指定关键字的记录,getSearchBoth()这个方法是根据所匹配的关键字来得到所需要的记录。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
.....
// Environment and database opens omitted for clarity.
// Environment and database may be opened read-only.
String aKey = "myFirstKey";
try {
// Create a pair of DatabaseEntry objects. theKey
// is used to perform the search. theData is used
// to store the data returned by the get() operation.
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry();
// Perform the get.
if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
// Recreate the data String.
byte[] retData = theData.getData();
String foundData = new String(retData);
System.out.println("For key: '" + aKey + "' found data: '" +
foundData + "'.");
} else {
System.out.println("No record found for key '" + aKey + "'.");
}
} catch (Exception e) {
// Exception handling goes here
}
|
- 删除数据库中的记录,一般是用Database.delete()方法,若数据库中存在重复的记录,要删除掉具有重复的关键字的记录的话,就会将所有具有该关键字的记录都删除掉了。也就是删除掉了一个记录的集合。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
.....
// Environment and database opens omitted for clarity.
// Environment and database can NOT be opened read-only.
try {
String aKey = "myFirstKey";
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
// Perform the deletion. All records that use this key are
// deleted.
myDatabase.delete(null, theKey);
} catch (Exception e) {
// Exception handling goes here
}
|
这里是根据指定的关键字"myFirstKey",来删除掉指定的记录,若该记录有重复的话,那么就会删掉该关键字的所有的记录集合。
- 游标的操作
游标的各种操作和数据库的各种操作都差不多。方法大体上是一样的。
- 游标的建立和关闭
游标也是建立在数据库基础之上的,因此,游标需要得到数据库的对象。
import com.sleepycat.je.Environment;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.CursorConfig;
import com.sleepycat.je.Cursor;
import java.io.File;
......
Environment myDbEnvironment = null;
Database myDatabase = null;
Cursor myCursor = null;
try {
myDbEnvironment = new Environment(new File("/export/dbEnv"), null);
myDatabase = myDbEnvironment.openDatabase(null, "myDB", null);
myCursor = myDatabase.openCursor(null, null);
} catch (DatabaseException dbe) {
// Exception handling goes here ...
}
|
从这里可以看到游标是建立在数据库基础之上的。
游标的关闭直接调用cursor.close()方法就可以了。
- 用游标插入数据到数据库
这里也是采用的put(),putNoDupData(),putNoOverwrite()三个方法来实现的,它们的使用方法和数据库的插入方法一样,这几个方法的区别也是在于对重复记录的判断上,具体的区别请看有关的资料。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.OperationStatus;
.....
// Create the data to put into the database
String key1str = "My first string";
String data1str = "My first data";
String key2str = "My second string";
String data2str = "My second data";
String data3str = "My third data";
Cursor cursor = null;
try {
...
// Database and environment open omitted for brevity
...
DatabaseEntry key1 = new DatabaseEntry(key1str.getBytes("UTF-8"));
DatabaseEntry data1 = new DatabaseEntry(data1str.getBytes("UTF-8"));
DatabaseEntry key2 = new DatabaseEntry(key2str.getBytes("UTF-8"));
DatabaseEntry data2 = new DatabaseEntry(data2str.getBytes("UTF-8"));
DatabaseEntry data3 = new DatabaseEntry(data3str.getBytes("UTF-8"));
// Open a cursor using a database handle
cursor = myDatabase.openCursor(null, null);
// Assuming an empty database.
OperationStatus retVal = cursor.put(key1, data1); // SUCCESS
retVal = cursor.put(key2, data2); // SUCCESS
retVal = cursor.put(key2, data3); // SUCCESS if dups allowed,
// KEYEXIST if not.
} catch (Exception e) {
// Exception handling goes here
} finally {
// Make sure to close the cursor
cursor.close();
}
|
在这个例子中,可以看到一开始的时候,cursor.put(key2, data2)执行后,在数据库中就已经有了key2的记录,后来,要调用了cursor.put(key2, data3)方法后,由于在数据库中已经存在了一个key2的记录,现在又在这个key2基础上添加一个,若允许数据库是重复的,因此这里就替代掉了原来的data2的数据了,现在是data3了。
- 用游标来得到数据和检索数据
使用游标最大的优点还是在于能够很方便的检索记录。用游标得到记录可以用getNext(),getPrev()等方法。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.LockMode;
.....
Cursor cursor = null;
try {
...
// Database and environment open omitted for brevity
...
// Open the cursor.
cursor = myDatabase.openCursor(null, null);
// Cursors need a pair of DatabaseEntry objects to operate. These hold
// the key and data found at any given position in the database.
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
// To iterate, just call getNext() until the last database record has been
// read. All cursor operations return an OperationStatus, so just read
// until we no longer see OperationStatus.SUCCESS
while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
// getData() on the DatabaseEntry objects returns the byte array
// held by that object. We use this to get a String value. If the
// DatabaseEntry held a byte array representation of some other data
// type (such as a complex object) then this operation would look
// considerably different.
String keyString = new String(foundKey.getData());
String dataString = new String(foundData.getData());
System.out.println("Key - Data : " + keyString + " - " + dataString + "");
}
} catch (DatabaseException de) {
System.err.println("Error accessing database." + de);
} finally {
// Cursors must be closed.
cursor.close();
}
|
在这里例子实际上就是遍历数据库所有的记录,将它打印出来,也可以使用getPrev()方法,也可以实现遍历数据库的操作。在重复的记录中,用数据库就无法操作,用游标就可以实现对重复记录的访问,也是使用这几个方法。
检索关键字是使用游标的getSearchKey(),getSearchKeyRange(),getSearchBoth(),getSearchBothRange()方法,这些方法的区别在于匹配的操作,具体的区别请参考有关的资料。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.LockMode;
.....
// For this example, hard code the search key and data
String searchKey = "Al";
String searchData = "Fa";
Cursor cursor = null;
try {
...
// Database and environment open omitted for brevity
...
// Open the cursor.
cursor = myDatabase.openCursor(null, null);
DatabaseEntry theKey =
new DatabaseEntry(searchKey.getBytes("UTF-8"));
DatabaseEntry theData =
new DatabaseEntry(searchData.getBytes("UTF-8"));
// Open a cursor using a database handle
cursor = myDatabase.openCursor(null, null);
// Perform the search
OperationStatus retVal = cursor.getSearchBothRange(theKey, theData,
LockMode.DEFAULT);
// NOTFOUND is returned if a record cannot be found whose key begins
// with the search key AND whose data begins with the search data.
if (retVal == OperationStatus.NOTFOUND) {
System.out.println(searchKey + "/" + searchData +
" not matched in database " +
myDatabase.getDatabaseName());
} else {
// Upon completing a search, the key and data DatabaseEntry
// parameters for getSearchBothRange() are populated with the
// key/data values of the found record.
String foundKey = new String(theKey.getData());
String foundData = new String(theData.getData());
System.out.println("Found record " + foundKey + "/" + foundData +
"for search key/data: " + searchKey +
"/" + searchData);
}
} catch (Exception e) {
// Exception handling goes here
} finally {
// Make sure to close the cursor
cursor.close();
}
|
这个例子,用的是getSearchBothRange()方法,它主要是用来查询匹配这个关键字和该关键字的数据的所有记录。 Cursor.count()这个方法,是用来统计当前键的出现的总的记录数。
- 用游标删除数据库中的数据,用cursor.delete()方法,和数据库中的delete()方法用法一样。不在举例说明了。
- 使用游标来代替当前键的值,用cursor.putCurrent()方法来实现,这在数据库中的操作方法中是很难实现的,用游标的这个方法,可以很方便的实现该操作。
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.LockMode;
......
Cursor cursor = null;
try {
...
// Database and environment open omitted for brevity
...
// Create DatabaseEntry objects
// searchKey is some String.
DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry();
// Open a cursor using a database handle
cursor = myDatabase.openCursor(null, null);
// Position the cursor. Ignoring the return value for clarity
OperationStatus retVal = cursor.getSearchKey(theKey, theData,
LockMode.DEFAULT);
// Replacement data
String replaceStr = "My replacement string";
DatabaseEntry replacementData =
new DatabaseEntry(replaceStr.getBytes("UTF-8"));
cursor.putCurrent(replacementData);
} catch (Exception e) {
// Exception handling goes here
} finally {
// Make sure to close the cursor
cursor.close();
}
|
这里的操作是用来代替掉指定的关键字的值,但是若有重复记录的话,就无法实现了。
- 事务的处理
Berkeley DB Java Edition提供了全部的事务的ACID的所有属性。(Atomicity,Consistency,Isolation,Durability)。
在Berkeley DB中使用事务时,可以很方便的配置和使用:
- 需要在数据库环境中配置事务的操作为可用的,EnvironmentConfig.setTransactional(true),这样就设置好了数据库环境下可以方便的使用事务。
- 在数据库中也要设置事务为可用的,DatabaseConfig.setTransactional(true),这样数据库就设置好了事务的处理。
- 接下来就可以在程序中使用事务了,在需要的地方插入transaction.commit(),提交事务。
- 数据备份和恢复
- 数据的备份分为两种:一种是部分备份,另一种是全部备份。它们的共同点就是拷贝所有的log files(.jdb)文件从数据库的环境目录到所要归档的目录或备份媒体。在这之前,必须要关闭事务,若存在事务,就无法它们的区别就是:部分备份是从最后一次备份开始到凡是修改过的或新增加的记录都需要备份,而全部备份是将所有的数据库信息,包括内存缓存中的数据都要备份,不过这需要停止写操作。
- 数据的恢复:简单的说就是将备份的log files文件拷贝到数据库的环境目录下,这里可以是增量备份,也可以是全部的备份,一般都是增量恢复,这些操作必须要关闭JE的应用程序。
- 其它
在这里只是说一下je.properties文件,这个文件是用来提供配置Berkeley DB的后台以及整体系统运行的参数,有的参数在je.properties文件中可以设置,在程序中也可以设置,但是在这个文件里的参数优先于程序中设置的参数。这个文件必须放在数据库环境的根目录下,这样系统才能执行该文件中的参数。
分享到:
相关推荐
Berkeley DB Java Edition (JE) 官方7.5.11下载版本。 相关介绍 https://blog.csdn.net/hadues/article/details/80854288
**Berkeley DB Java Edition**,简称BDBJE,是由Oracle公司开发的一款高度可移植的、基于文件系统的数据存储解决方案,特别适用于需要高效、可靠且无服务器的数据管理的应用场景。这款数据库系统采用B+树作为其核心...
**Berkeley DB Java Edition 5.0.73** Berkeley DB Java Edition(简称BDB JE)是一款由Oracle公司开发的高性能、轻量级的NoSQL数据库系统。它以其高效能、可扩展性和可靠性在处理大规模数据存储时受到广泛欢迎,...
Berkeley DB Java Edition (JE) 是一款开源的嵌入式数据库管理系统,由Sleepycat Software开发,现归Oracle公司所有。这款数据库系统以其键值(K/V)存储模型为特色,适用于需要高性能、可伸缩性及事务处理能力的应用...
Berkeley DB Java Edition(JE)是一种为Java程序提供内嵌式、事务保护的数据库引擎,它继承了Berkeley DB家族的优点,包括快速、可靠和具备容错能力的数据管理特性。为了深入理解其数据存储结构,有必要对JE使用的B...
Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。 能够高效率的处理1到1百万条记录,制约JE数据库的往往是硬件系统,而不是JE本身。 多线程支持,JE使用超时的方式来处理...
《Berkeley DB Java Edition 4.0.92 开发包详解》 Berkeley DB Java Edition(简称BDB JE)是Oracle公司推出的一款强大的、高度可定制的嵌入式数据库系统,尤其适用于Java应用程序。这款数据库引擎以其轻量级、高...
Berkeley DB Java Edition JE 是一个完全用JAVA写的 它适合于管理海量的 简单的数据 能够高效率的处理1到1百万条记录 制约JE数据库的往往是硬件系统 而不是JE本身 多线程支持 JE使用超时的方式来处理线程间的死琐...
**Java嵌入式NoSQL数据库之Berkeley DB Java Edition** Berkeley DB Java Edition(简称BDB JE)是一种高性能、轻量级的嵌入式数据库系统,由Oracle公司开发,广泛应用于需要快速数据存储和检索的应用场景。它并非...
Oracle Berkeley DB Java 版是一个开源的、可嵌入的事务存储引擎,是完全用 Java 编写的。与 Oracle Berkeley DB 类似,Oracle Berkeley DB Java 版在应用程序的地址空间中执行,没有客户端/服务器通信的开销,从而...
NULL 博文链接:https://xpenxpen.iteye.com/blog/2124921
自己稍微封装了一下,可以当成简单的map来使用。
这可能是BerkeleyDB Java Edition的jar文件,表示BerkeleyDB Java版的7.5.11版本。这个文件通常会包含以下组件: 1. **BerkeleyDB引擎**:这是数据库的核心部分,处理数据的读写操作,包括事务处理、并发控制、恢复...
Berkeley DB Java 版直接持久层基础1 Berkeley DB Java 版直接持久层基础1是指使用 Berkeley DB Java 版本来实现直接持久层的技术基础。直接持久层是一种数据访问技术,允许Java应用程序直接访问数据库,而不需要...
《嵌入式Berkeley DB Java版与Derby技术研究》一文主要探讨了两种典型的嵌入式数据库技术——Berkeley DB Java Edition和Apache Derby。嵌入式数据库在资源有限的环境中,如嵌入式系统,因其体积小、功能齐全、可...
Berkeley DB是一款由Oracle公司开发的嵌入式数据库系统,被广泛应用于许多软件项目中,尤其是在需要快速、轻量级数据存储解决方案的场景下。它提供了键值对存储模式,适用于构建高性能的数据缓存和数据库应用程序。...