介绍和使用Berkeley DB Java Edition(嵌入式数据库)
一、 简介
?????? Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。
??????? 能够高效率的处理1到1百万条记录,制约JE数据库的往往是硬件系统,而不是JE本身。
??????? 多线程支持,JE使用超时的方式来处理线程间的死琐问题。
??????? Database都采用简单的key/value对应的形式。
??????? 事务支持。
??????? 允许创建二级库。这样我们就可以方便的使用一级key,二级key来访问我们的数据。
??????? 支持RAM缓冲,这样就能减少频繁的IO操作。
??????? 支持日志。
??????? 数据备份和恢复。
??????? 游标支持。
二、?? 获取JE
JE下载地址:
http://www.oracle.com/technology/software/products/berkeley-db/je/index.html
解开包后 把JE_HOME/lib/je-<version>.jar 中的jar文件添加到你的环境变量中就可以使用je了。
相关帮助文档可以参考 JE_HOME/docs/index.html
源代码见JE_HOME/src/*.*
三、???? JE常见的异常
DatabaseNotFoundException 当没有找到指定的数据库的时候会返回这个异常
DeadlockException 线程间死锁异常
RunRecoveryException 回收异常,当发生此异常的时候,你必须得重新打开环境变量。
四、???? 关于日志文件必须了解的六项
JE的日志文件跟其他的数据库的日志文件不太一样,跟C版的DBD也是有区别的
??????? JE的日志文件只能APPEND,第一个日志文件名是 00000000.jdb,当他增长到一定大小的时候(默认是10M),开始写第二个日志文件00000001.jdb,已此类推。
??????? 跟C版本有所不同,JE的数据日志和事务日志是放在一起的,而不是分开放的。
??????? JE cleaner负责清扫没用到的磁盘空间,删除后,或者更新后新的记录会追加进来,而原有的记录空间就不在使用了,cleaner负责清理不用的空间。
??????? 清理并不是立即进行的,当你关闭你的数据库环境后,通过调用一个cleaner方法来清理。
?????? 清理也不是只动执行的,需要你自己手动调用cleaner 方法来定时清理的。
??????? 日志文件的删除仅发生在检查点之后。cleaner准备出哪些log 文件需要被删除,当检查点过后,删掉一些不在被使用的文件。每写20M的日志文件就执行一次检查点,默认下。
JE的英文文档:http://www.oracle.com/technology/documentation/berkeley-db/je/GettingStartedGuide/index.html
JE的中文文档(不全):http://fesir.itpub.net/post/4728/253789
http://fesir.itpub.net/post/4728/253789
上面大概介绍一下,接下来是我在工作中写的一个例子(仅供参考):
Java代码 view plaincopy to clipboardprint?
package src.util;??
?
import java.io.File;??
import java.util.List;??
?
import junit.framework.TestCase;??
import src.com.bizjato.b2b.entity.Suppliers;??
?
import com.sleepycat.bind.EntryBinding;??
import com.sleepycat.bind.serial.SerialBinding;??
import com.sleepycat.bind.serial.StoredClassCatalog;??
import com.sleepycat.je.Cursor;??
import com.sleepycat.je.CursorConfig;??
import com.sleepycat.je.Database;??
import com.sleepycat.je.DatabaseConfig;??
import com.sleepycat.je.DatabaseEntry;??
import com.sleepycat.je.DatabaseException;??
import com.sleepycat.je.Environment;??
import com.sleepycat.je.EnvironmentConfig;??
import com.sleepycat.je.EnvironmentMutableConfig;??
import com.sleepycat.je.LockMode;??
import com.sleepycat.je.OperationStatus;??
?
/**?
?* 嵌入式数据库?
?*??
?* @author zhangqinjian?
?*?
?*/?
public class Jedtion extends TestCase {??
?
??? private static final String RESOURCE = ".//src//util//importData";??
??? private Environment env;??
?
??? private Database db, classDB;??
?
??? private StoredClassCatalog classCatalog;??
??? /**?
???? * 初始化,设置数据库的环境和创建数据库?
???? */?
??? public void setUp() throws Exception {??
?
??????? env = new Environment(new File(".//src//util//importData"), null);??
??????? EnvironmentMutableConfig envMutableConfig = new EnvironmentMutableConfig();??
??????? envMutableConfig.setTxnNoSync(true);??
??????? env.setMutableConfig(envMutableConfig);??
?
??????? DatabaseConfig dbConfig = new DatabaseConfig();??
??????? dbConfig.setAllowCreate(true);??
??????? db = env.openDatabase(null, "myDB", dbConfig);??
??????? classDB = env.openDatabase(null, "classDB", dbConfig);??
??????? classCatalog = new StoredClassCatalog(classDB);??
??? }??
??? // test: put key-value??
??? public void testPut(String key, Suppliers supp) throws Exception {??
??????? EntryBinding dataBinding = new SerialBinding(classCatalog,??
??????????????? Suppliers.class);??
??????? DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("UTF-8"));??
??????? DatabaseEntry dataEntry = new DatabaseEntry();??
??????? dataBinding.objectToEntry(supp, dataEntry);??
??????? db.put(null, keyEntry, dataEntry);??
??? }??
??? // test: get??
??? public void testGet() throws Exception {??
??????? EnvironmentConfig envConfig = new EnvironmentConfig();??
??????? envConfig.setAllowCreate(true);??
??????? // envConfig.setReadOnly(true);??
??????? env = new Environment(new File(".//src//util//importData"), envConfig);??
??????? List myDbNames = env.getDatabaseNames();??
??????? System.out.println("Database size: " + myDbNames.size());??
??????? for (int i = 0; i < myDbNames.size(); i++) {??
??????????? System.out.println("Database Name: " + (String) myDbNames.get(i));??
??????? }??
?
??????? DatabaseConfig dbConfig = new DatabaseConfig();??
??????? dbConfig.setAllowCreate(true);??
??????? // dbConfig.setReadOnly(true);??
??????? db = env.openDatabase(null, "myDB", dbConfig);??
??????? classDB = env.openDatabase(null, "classDB", dbConfig);??
??????? classCatalog = new StoredClassCatalog(classDB);??
?
??????? System.out.println("Db: " + db.count());??
?
??????? EntryBinding dataBinding = new SerialBinding(classCatalog,??
??????????????? Suppliers.class);??
?
??????? DatabaseEntry keyEntry = new DatabaseEntry("key".getBytes("UTF-8"));??
??????? DatabaseEntry dataEntry = new DatabaseEntry();??
??????? db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);??
??????? Suppliers p = (Suppliers) dataBinding.entryToObject(dataEntry);??
??????? System.out.println(p.getCategory());??
??? }??
?
??? /**?
???? * test: read database?
???? * @throws Exception?
???? */?
??? public void testStore() throws Exception {??
?
??????? EnvironmentConfig envConfig = new EnvironmentConfig();??
??????? envConfig.setAllowCreate(true);??
??????? env = new Environment(new File(".//src//util//importData"), envConfig);??
?
??????? DatabaseConfig dbConfig = new DatabaseConfig();??
??????? dbConfig.setAllowCreate(true);??
??????? db = env.openDatabase(null, "myDB", dbConfig);??
??????? classDB = env.openDatabase(null, "classDB", dbConfig);??
??????? classCatalog = new StoredClassCatalog(classDB);??
?
??????? EntryBinding dataBinding = new SerialBinding(classCatalog,Suppliers.class);??
?
??????? Cursor cursor = null;??
??????? CursorConfig config = new CursorConfig();??
??????? config.setDirtyRead(true);??
??????? cursor = db.openCursor(null, config);?????? // open cursor??
?
??????? 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());??
??????????????????
??????????????? Suppliers supp = (Suppliers)dataBinding.entryToObject(foundData);??
??????????????? System.out.println("Key - Data : " + keyString + " - "?
??????????????????????? + supp.getCompanyName() + "");??
??????????? }??
??????? } catch (DatabaseException de) {??
??????????? System.err.println("Error accessing database." + de);??
??????? } finally {??
??????????? // Cursors must be closed.??
??????????? cursor.close();??
??????????? db.close();??
??????????? classDB.close();??
??????????? env.cleanLog();??
??????????? env.close();??
??????? }??
?
??? }??
?
??? public void tearDown() throws Exception {??
??????? db.close();??
??????? classDB.close();??
??????? env.cleanLog();??
??????? env.close();??
??? }??
?
??? public static void main(String[] args) {??
??????? Jedtion t = new Jedtion();??
??????? try {??
??????????? // t.setUp();??
??????????? // Suppliers supp = new Suppliers();??
??????????? // supp.setCategory("fivefive");??
??????????? // t.testPut("5",supp);??
??????????? // t.testGet();??
??????????? // t.testStore();??
??????????????????????? // t.tearDown();??
??????? } catch (Exception e) {??
??????????? // TODO Auto-generated catch block??
??????????? e.printStackTrace();??
??????? }??
?
??? }??
}?
?