您的位置:首页 > 编程语言 > Java开发

Berkeley DB Java Edition 使用手册

2011-12-02 20:45 381 查看
[align=center]Berkeley DB Java Edition使用说明[/align]
Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。
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常见的异常
DatabaseNotFoundException 当没有找到指定的数据库的时候会返回这个异常
RunRecoveryException 回收异常,当发生此异常的时候,你必须得重新打开环境变量。
关于日志文件必须了解的六项
JE的日志文件跟其他的数据库的日志文件不太一样,跟C版的DBD也是有区别的
JE的日志文件只能APPEND,第一个日志文件名是 00000000.jdb,当他增长到一定大小的时候(默认是10M),开始写第二个日志文件00000001.jdb,已此类推。
创建数据库环境
JE要求在任何DATABASE操作前,要先打开数据库环境,就像我们要使用数据库的 话必须得先建立连接一样。你可以通过数据库环境来创建和打开database,或者更改database名称和删除database.
可以通过Environments对象来打开环境,打开环境的时候设置的目录必须是已 经存在的目录,否则会出错误。默认情况下,如果指定的database不存在则不会自动创建一个新的detabase,但可以通过设置 setAllowCreate来改变这一情况。
打开database环境
示例:
package je.gettingStarted;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import java.io.File;
...
Environment myDbEnvironment = null;
try {
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);//如果不存在则创建一个
myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
} catch (DatabaseException dbe) {
}
关闭database环境
可以通过Environment.close()这个方法来关闭database环 境,当你完成数据库操作后一定要关闭数据库环境。
示例:
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
...
try {
if (myDbEnvironment != null) {
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
// Exception handling goes here
}
通常在关闭数据库连接的时候,有必要清理下日志,用以释放更多的磁盘空间。我们可以在Environment.close前执行下 Environment.cleanLog()来达到此目的。
示例:
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
...
try {
if (myDbEnvironment != null) {
myDbEnvironment.cleanLog(); // 在关闭环境前清理下日志
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
// Exception handling goes here
}
Database环境的配置
可以通过EnvironmentConfig这个对象来配置database环境。如 果想得到当前环境的配置信息则可以通过Environment.getConfig()方法得到当前环境的配置信息。
也可以使用EnvironmentMutableConfig来配置环境,其实 EnvironmentConfig是EnvironmentMutableConfig的子类,所以EnvironmentMutableConfig 能够使用的设置,EnvironmentConfig也同样能够使用。
如果你要获取当前环境的使用情况,那么你可以通过使用 EnvironmentStats.getNCacheMiss().来监视RAM cache命中率。EnvironmentStats可以由Environment.getStats()方法获取。
EnvironmentConfig常 见方法介绍
如果设置了true则表示当数据库环境不存在时候重新创建一个数据库环境,默认为false.
以只读方式打开,默认为false.
事务支持,如果为true,则表示当前环境支持事务处理,默认为false,不支持事务处理。
EnvironmentMutableConfig的 介绍
设置当前环境能够使用的RAM占整个JVM内存的百分比。
设置当前环境能够使用的最大RAM。单位BYTE
当提交事务的时候是否把缓存中的内容同步到磁盘中去。
true 表示不同步,也就是说不写磁盘
当提交事务的时候,是否把缓冲的log写到磁盘上
true 表示不同步,也就是说不写磁盘
示例一:
package je.gettingStarted;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import java.io.File;
...
Environment myDatabaseEnvironment = null;
try {
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
envConfig.setTransactional(true);
myDatabaseEnvironment =
new Environment(new File("/export/dbEnv"), envConfig);
} catch (DatabaseException dbe) {
System.err.println(dbe.toString());
System.exit(1);
}
package je.gettingStarted;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentMutableConfig;
import java.io.File;
...
try {
Environment myEnv = new Environment(new File("/export/dbEnv"), null);
EnvironmentMutableConfig envMutableConfig =
new EnvironmentMutableConfig();
envMutableConfig.setTxnNoSync(true);
myEnv.setMutableConfig(envMutableConfig);
} catch (DatabaseException dbe) {
// Exception handling goes here
}
示例三:
import com.sleepycat.je.Environment;
...
long cacheMisses = myEnv.getStats(null).getNCacheMiss();
...
Database操作
在BDB中,数据是以key/value方式成队出现的。
打开database
package je.gettingStarted;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import java.io.File;
...
Environment myDbEnvironment = null;
Database myDatabase = null;
...
try {
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
myDatabase = myDbEnvironment.openDatabase(null,
"sampleDatabase", dbConfig); //打开一个数据库,数据库名为
//sampleDatabase,数据库的配置为dbConfig
} catch (DatabaseException dbe) {
}
关闭database
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Database;
import com.sleepycat.je.Environment;
...
try {
if (myDatabase != null) {
myDatabase.close();
}
if (myDbEnvironment != null) {
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
}
设置数据库属性
如果是true的话,则当不存在此数据库的时候创建一个。
设置用于Btree比较的比较器,通常是用来排序
设置用来比较一个key有两个不同值的时候的大小比较器。
设置一个key是否允许存储多个值,true代表允许,默认false.
以独占的方式打开,也就是说同一个时间只能有一实例打开这个database。
以只读方式打开database,默认是false.
如果设置为true,则支持事务处理,默认是false,不支持事务。
使用示例:
package je.gettingStarted;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
...
// Environment open omitted for brevity
...
Database myDatabase = null;
try {
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
dbConfig.setSortedDuplicates(true);
myDatabase =
myDbEnv.openDatabase(null,
"sampleDatabase",
dbConfig);
} catch (DatabaseException dbe) {
// Exception handling goes here.
}
一些用来管理的方法
取得数据库的名称
如:String dbName = myDatabase.getDatabaseName();
取得包含这个database的环境信息
如:Environment theEnv = myDatabase.getEnvironment();
预先加载指定bytes的数据到RAM中。
如:myDatabase.preload(1048576l); // 1024*1024
返回当前环境下的数据库列表
如:
import java.util.List;
List myDbNames = myDbEnv.getDatabaseNames();
for(int i=0; i < myDbNames.size(); i++) {
System.out.println("Database Name: " + (String)myDbNames.get(i));
}
删除当前环境中指定的数据库。
如:
String dbName = myDatabase.getDatabaseName();
myDatabase.close();
myDbEnv.removeDatabase(null, dbName);
给当前环境下的数据库改名
如:
String newName = new String(oldName + ".new", "UTF-8");
myDatabase.close();
myDbEnv.renameDatabase(null, oldName, newName);
清空database内的所有数据,返回清空了多少条记录。
如:
Int numDiscarded= myEnv.truncate(null,
myDatabase.getDatabaseName(),true);
System.out.println("一共删除了 " + numDiscarded +" 条记录 从数据库 " + myDatabase.getDatabaseName());
Database 记录
[align=left]JE的记录包含两部分,key键值和value数据值,这 两个值都是通过DatabaseEntry对象封装起来,所以说如果要使用记录,则你必须创建两个DatabaseEntry对象,一个是用来做为 key,另外一个是做为value.[/align]
[align=left]DatabaseEntry能够支持任何的能够转换为 bytes数组形式的基本数据。包括所有的JAVA基本类型和可序列化的对象.[/align]
[align=left] [/align]
[align=left]使用记录[/align]
package je.gettingStarted;
import com.sleepycat.je.DatabaseEntry;
...
String aKey = "key";
String aData = "data";
try {
//设置key/value,注意DatabaseEntry内使用的是bytes数组
DatabaseEntry theKey=new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry theData=new DatabaseEntry(aData.getBytes("UTF-8"));
} catch (Exception e) {
}
byte[] myKey = theKey.getData();
byte[] myData = theData.getData();
String key = new String(myKey, "UTF-8");
String data = new String(myData, "UTF-8");
[align=left]读和写database 记录[/align]
[align=left] 读和写database记录的时候大体是基本一样的,唯一有区别的是每个key写是否允许写多条记录,默认情况下是不支持多条记录的。[/align]
[align=left] 向database中添加一条记录。如果你的database不支持一个key对应多个data或当前database中已经存在该key了,则使用此方 法将使用新的值覆盖旧的值。[/align]
[align=left]Database.putNoOverwrite()[/align]
[align=left] 向database中添加新值但如果原先已经有了该key,则不覆盖。不管database是否允许支持多重记录(一个key对应多个value),只要 存在该key就不允许添加,并且返回perationStatus.KEYEXIST信息。[/align]
[align=left]Database.putNoDupData()[/align]
[align=left] 想database中添加一条记录,如果database中已经存在了相同的 key和value则返回 OperationStatus.KEYEXIST.[/align]
[align=left]使用示例:[/align]
package je.gettingStarted;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
String aKey = "myFirstKey";
String aData = "myFirstData";
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
myDatabase.put(null, theKey, theData);
// Exception handling goes here
[align=left] 通过key和value来同时匹配,同样如果没有记录匹配key和value则会返回OperationStatus.NOTFOUND。[/align]
[align=left]使用示例:[/align]
package je.gettingStarted;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
...
String aKey = "myFirstKey";
try {
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry();

if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
byte[] retData = theData.getData();
String foundData = new String(retData, "UTF-8");
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
}
[align=left] 当然你也可以使用Environment.truncateDatabase()这个方法来清空database 中的所有记录。[/align]
[align=left]使用示例:[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] String aKey = "myFirstKey";[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));[/align]
[align=left] myDatabase.delete(null, theKey);[/align]
[align=left]} catch (Exception e) {[/align]
[align=left]}[/align]
[align=left] 当你对database进行了写操作的时候,你的修改不一定马上就能生 效,有的时候他仅仅是缓存在RAM中,如果想让你的修改立即生效,则可以使用Environment.sync()方法来把数据同步到磁盘中去。[/align]
[align=left]你可以使用DatabaseEntry来绑定基本的 JAVA数据类型,主要有String、Character、Boolean、Byte、Short、Integer、Long、Float、 Double.[/align]
[align=left] package je.gettingStarted;[/align]
[align=left] import com.sleepycat.bind.EntryBinding;[/align]
[align=left] import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left] import com.sleepycat.je.DatabaseEntry;[/align]
[align=left] String aKey = "myLong";[/align]
[align=left] DatabaseEntry theKey = new[/align]
[align=left] DatabaseEntry(aKey.getBytes("UTF-8")); [/align]
[align=left] Long myLong = new Long(123456789l);[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] EntryBinding myBinding = [/align]
[align=left] TupleBinding.getPrimitiveBinding(Long.class);[/align]
[align=left] myBinding.objectToEntry(myLong, theData);[/align]
[align=left] myDatabase.put(null, theKey, theData);[/align]
[align=left] } catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left] package je.gettingStarted;[/align]
[align=left] import com.sleepycat.bind.EntryBinding;[/align]
[align=left] import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left] import com.sleepycat.je.Database;[/align]
[align=left] import com.sleepycat.je.DatabaseEntry;[/align]
[align=left] import com.sleepycat.je.LockMode;[/align]
[align=left] import com.sleepycat.je.OperationStatus;[/align]
[align=left] Database myDatabase = null;[/align]
[align=left] String aKey = "myLong";[/align]
[align=left] DatabaseEntry theKey = new[/align]
[align=left] DatabaseEntry(aKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] EntryBinding myBinding = [/align]
[align=left] TupleBinding.getPrimitiveBinding(Long.class);[/align]
[align=left] OperationStatus retVal = myDatabase.get(null, theKey, theData,[/align]
[align=left] LockMode.DEFAULT);[/align]
[align=left] String retKey = null;[/align]
[align=left] if (retVal == OperationStatus.SUCCESS) {[/align]
[align=left] Long theLong = (Long) myBinding.entryToObject(theData);[/align]
[align=left] retKey = new String(theKey.getData(), "UTF-8");[/align]
[align=left] System.out.println("For key: '" + retKey + "' found Long: '" +[/align]
[align=left] theLong + "'.");[/align]
[align=left] System.out.println("No record found for key '" + retKey + "'.");[/align]
[align=left] } catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]可序列化的对象的绑定[/align]
[align=left]实例化catalog类,这个时候你可以使用 com.sleepycat.bind.serial.StoredClassCatalog,来存储你的类信息。[/align]
[align=left]通过 com.sleepycat.bind.serial.SerialBinding来绑定数据和类。[/align]
[align=left]示例:[/align]
[align=left]创建一个可序列化的对象[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import java.io.Serializable;[/align]
[align=left]public class MyData implements Serializable {[/align]
[align=left] private long longData;[/align]
[align=left] private double doubleData;[/align]
[align=left] private String description;[/align]
[align=left] MyData() {[/align]
[align=left] longData = 0;[/align]
[align=left] doubleData = 0.0;[/align]
[align=left] description = null;[/align]
[align=left] }[/align]
[align=left] public void setLong(long data) {[/align]
[align=left] longData = data;[/align]
[align=left] }[/align]
[align=left] public void setDouble(double data) {[/align]
[align=left] doubleData = data;[/align]
[align=left] }[/align]
[align=left] public void setDescription(String data) {[/align]
[align=left] description = data;[/align]
[align=left] }[/align]
[align=left] public long getLong() {[/align]
[align=left] return longData;[/align]
[align=left] }[/align]
[align=left] public double getDouble() {[/align]
[align=left] return doubleData;[/align]
[align=left] }[/align]
[align=left] public String getDescription() {[/align]
[align=left] return description;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.EntryBinding;[/align]
[align=left]import com.sleepycat.bind.serial.StoredClassCatalog;[/align]
[align=left]import com.sleepycat.bind.serial.SerialBinding;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseConfig;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]...[/align]
[align=left]String aKey = "myData";[/align]
[align=left]MyData data2Store = new MyData();[/align]
[align=left]data2Store.setLong(123456789l);[/align]
[align=left]data2Store.setDouble(1234.9876543);[/align]
[align=left]data2Store.setDescription("A test instance of this class");[/align]
[align=left]try {[/align]
[align=left] DatabaseConfig myDbConfig = new DatabaseConfig();[/align]
[align=left] myDbConfig.setAllowCreate(true);[/align]
[align=left] myDbConfig.setSortedDuplicates(true);[/align]
[align=left] Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);[/align]
[align=left] myDbConfig.setSortedDuplicates(false);[/align]
[align=left] Database myClassDb = myDbEnv.openDatabase(null, "classDb", myDbConfig);[/align]
[align=left] StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);[/align]
[align=left] EntryBinding dataBinding = new SerialBinding(classCatalog,[/align]
[align=left] MyData.class);[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));[/align]
[align=left]里写数据[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] dataBinding.objectToEntry(data2Store, theData);[/align]
[align=left] myDatabase.put(null, theKey, theData);[/align]
[align=left]} catch (Exception e) {[/align]
[align=left]}[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.EntryBinding;[/align]
[align=left]import com.sleepycat.bind.serial.StoredClassCatalog;[/align]
[align=left]import com.sleepycat.bind.serial.SerialBinding;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseConfig;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]...[/align]
[align=left]// The key data.[/align]
[align=left]String aKey = "myData";[/align]
[align=left]try {[/align]
[align=left] DatabaseConfig myDbConfig = new DatabaseConfig();[/align]
[align=left] myDbConfig.setAllowCreate(false);[/align]
[align=left] Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);[/align]
[align=left] Database myClassDb = myDbEnv.openDatabase(null, "classDb", myDbConfig);[/align]
[align=left] StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);[/align]
[align=left] EntryBinding dataBinding = new SerialBinding(classCatalog,[/align]
[align=left] MyData.class);[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] myDatabase.get(null, theKey, theData, LockMode.DEFAULT);[/align]
[align=left] // Recreate the MyData object from the retrieved DatabaseEntry using[/align]
[align=left]MyData retrievedData=(MyData)dataBinding.entryToObject(theData);[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
[align=left]自定义对象的绑定[/align]
[align=left]通过 com.sleepycat.bind.tuple.TupleBinding class来创建一个tuple binding。[/align]
[align=left]使用示例:[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]public class MyData2 {[/align]
[align=left] private long longData;[/align]
[align=left] private Double doubleData;[/align]
[align=left] private String description;[/align]
[align=left] public MyData2() {[/align]
[align=left] longData = 0;[/align]
[align=left] doubleData = new Double(0.0);[/align]
[align=left] description = "";[/align]
[align=left] }[/align]
[align=left] public void setLong(long data) {[/align]
[align=left] longData = data;[/align]
[align=left] }[/align]
[align=left] public void setDouble(Double data) {[/align]
[align=left] doubleData = data;[/align]
[align=left] }[/align]
[align=left] public void setString(String data) {[/align]
[align=left] description = data;[/align]
[align=left] }[/align]
[align=left] public long getLong() {[/align]
[align=left] return longData;[/align]
[align=left] }[/align]
[align=left] public Double getDouble() {[/align]
[align=left] return doubleData;[/align]
[align=left] }[/align]
[align=left] public String getString() {[/align]
[align=left] return description;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleInput;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleOutput;[/align]
[align=left]public class MyTupleBinding extends TupleBinding {[/align]
[align=left] public void objectToEntry(Object object, TupleOutput to) {[/align]
[align=left] MyData2 myData = (MyData2)object;[/align]
[align=left] to.writeDouble(myData.getDouble().doubleValue());[/align]
[align=left] to.writeLong(myData.getLong());[/align]
[align=left] to.writeString(myData.getString());[/align]
[align=left] }[/align]
[align=left] public Object entryToObject(TupleInput ti) {[/align]
[align=left] Double theDouble = new Double(ti.readDouble());[/align]
[align=left] long theLong = ti.readLong();[/align]
[align=left] String theString = ti.readString();[/align]
[align=left] MyData2 myData = new MyData2();[/align]
[align=left] myData.setDouble(theDouble);[/align]
[align=left] myData.setLong(theLong);[/align]
[align=left] myData.setString(theString);[/align]
[align=left] return myData;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]...[/align]
[align=left]TupleBinding keyBinding = new MyTupleBinding();[/align]
[align=left]MyData2 theKeyData = new MyData2();[/align]
[align=left]theKeyData.setLong(123456789l);[/align]
[align=left]theKeyData.setDouble(new Double(12345.6789));[/align]
[align=left]theKeyData.setString("My key data");[/align]
[align=left]DatabaseEntry myDate = new DatabaseEntry();[/align]
[align=left]try {[/align]
[align=left] // 把theKeyData 存储到DatabaseEntry里[/align]
[align=left] keyBinding.objectToEntry(theKeyData,[/align]
[align=left] ...[/align]
[align=left] ...[/align]
[align=left] // Retrieve the key data[/align]
[align=left] theKeyData = (MyData2) keyBinding.entryToObject([/align]
[align=left]} catch (Exception e) {[/align]
[align=left]}[/align]
[align=left] JE是使用BTrees来组织结构的,这意味着当对database的读 和写需要涉及BTrees间的节点比较。这些比较在key间是经常的发生的。如果你的database支持多重记录,那么也会存在data间的比较。[/align]
[align=left] 默认的情况JE的比较器是按照字节的方式来进行比较的,这通常情况下能处理大多数的情况。但有的时候确实需要自定义比较器用于特殊的通途,比如说按照 key来排序。[/align]
[align=left]示例:[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import java.util.Comparator;[/align]
[align=left]public class MyDataComparator implements Comparator {[/align]
[align=left] public MyDataComparator() {}[/align]
[align=left] public int compare(Object d1, Object d2) {[/align]
[align=left] byte[] b1 = (byte[])d1;[/align]
[align=left] byte[] b2 = (byte[])d2;[/align]
[align=left] String s1 = new String(b1, "UTF-8");[/align]
[align=left] String s2 = new String(b2, "UTF-8");[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left] 如果为true则代表让database使用 DatabaseConfig.setBtreeComparator()设置的比较器来代替默认的比较器。[/align]
[align=left] 如果为true则代表让database使用 DatabaseConfig. setDuplicateComparator()设置 的比 较器来代替默认的比较器。[/align]
[align=left]使用示例:[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseConfig;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import java.util.Comparator; [/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] DatabaseConfig myDbConfig = new DatabaseConfig();[/align]
[align=left] myDbConfig.setAllowCreate(true);[/align]
[align=left] myDbConfig.setDuplicateComparator(MyDataComparator.class);[/align]
[align=left] myDbConfig.setSortedDuplicates(true);[/align]
[align=left] Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);[/align]
[align=left]} catch (DatabaseException dbe) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.CursorConfig;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.Environment;[/align]
[align=left]import java.io.File;[/align]
[align=left]...[/align]
[align=left]Environment myDbEnvironment = null;[/align]
[align=left]Database myDatabase = null;[/align]
[align=left]Cursor myCursor = null;[/align]
[align=left]try {[/align]
[align=left] myDbEnvironment = new Environment(new File("/export/dbEnv"), null);[/align]
[align=left] myDatabase = myDbEnvironment.openDatabase(null, "myDB", null);[/align]
[align=left] myCursor = myDatabase.openCursor(null, null);[/align]
[align=left]} catch (DatabaseException dbe) {[/align]
[align=left] // Exception handling goes here ...[/align]
[align=left]}[/align]
关闭游标示例:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.Environment;[/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left]} catch ... {[/align]
[align=left]} finally {[/align]
[align=left] try {[/align]
[align=left] if (myCursor != null) {[/align]
[align=left] myCursor.close();[/align]
[align=left] }[/align]
[align=left] if (myDatabase != null) {[/align]
[align=left] myDatabase.close();[/align]
[align=left] }[/align]
[align=left] if (myDbEnvironment != null) {[/align]
[align=left] myDbEnvironment.close();[/align]
[align=left] }[/align]
[align=left] } catch(DatabaseException dbe) {[/align]
[align=left] System.err.println("Error in close: " + dbe.toString());[/align]
[align=left] }[/align]
[align=left]}[/align]
通过游标来获取记录
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.LockMode; [/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] DatabaseEntry foundKey = new DatabaseEntry();[/align]
[align=left] DatabaseEntry foundData = new DatabaseEntry();[/align]
[align=left] // 通过cursor.getNex方法来遍历记录[/align]
[align=left] while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==[/align]
[align=left] OperationStatus.SUCCESS) {[/align]
[align=left] String keyString = new String(foundKey.getData(), "UTF-8");[/align]
[align=left] String dataString = new String(foundData.getData(), "UTF-8");[/align]
[align=left] System.out.println("Key | Data : " + keyString + " | " +[/align]
[align=left] dataString + "");[/align]
[align=left] }[/align]
[align=left]} catch (DatabaseException de) {[/align]
[align=left] System.err.println("Error accessing database." + de);[/align]
[align=left]} finally {[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
使用示例二:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.LockMode; [/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] // Open the cursor.[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] DatabaseEntry foundKey = new DatabaseEntry();[/align]
[align=left] DatabaseEntry foundData = new DatabaseEntry();[/align]
[align=left] // 使用cursor.getPrev方法来遍历游标获取数据[/align]
[align=left] while (cursor.getPrev(foundKey, foundData, LockMode.DEFAULT)[/align]
[align=left] == OperationStatus.SUCCESS) {[/align]
[align=left] String theKey = new String(foundKey.getData(), "UTF-8");[/align]
[align=left] String theData = new String(foundData.getData(), "UTF-8");[/align]
[align=left] System.out.println("Key | Data : " + theKey + " | " + theData + "");[/align]
[align=left] }[/align]
[align=left]} catch (DatabaseException de) {[/align]
[align=left] System.err.println("Error accessing database." + de);[/align]
[align=left]} finally {[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
你可以通过游标方式搜索你的database记录,你也可以通过一个key来搜索你的记录,同样的你也可以通过key和value组合在一起来搜索记录。 如果查询失败,则游标会返回OperationStatus.NOTFOUND。
Cursor.getSearchKey()
Cursor.getSearchKeyRange()
Cursor.getSearchBoth()
Cursor.getSearchBothRange()
比如说database存在如下的key/value记录,,大小比较是通过你设置的比较器来完成的,如果没有设置则使用默认的比较器。
假设你的database存在如下的记录。
Alabama/Athens Alabama/Florence Alaska/Anchorage Alaska/Fairbanks Arizona/Avondale Arizona/Florence
然后查询
使用示例:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]String searchKey = "Alaska";[/align]
[align=left]String searchData = "Fa";[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] DatabaseEntry theKey =[/align]
[align=left] new DatabaseEntry(searchKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData =[/align]
[align=left] new DatabaseEntry(searchData.getBytes("UTF-8"));[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] OperationStatus retVal = cursor.getSearchBothRange(theKey,[/align]
[align=left] theData, LockMode.DEFAULT);[/align]
[align=left] if (retVal == OperationStatus.NOTFOUND) {[/align]
[align=left] System.out.println(searchKey + "/" + searchData +[/align]
[align=left] " not matched in database " +[/align]
[align=left] myDatabase.getDatabaseName());[/align]
[align=left] } else {[/align]
[align=left] String foundKey = new String(theKey.getData(), "UTF-8");[/align]
[align=left] String foundData = new String(theData.getData(), "UTF-8");[/align]
[align=left] System.out.println("Found record " + foundKey + "/" + foundData +[/align]
[align=left] "for search key/data: " + searchKey +[/align]
[align=left] "/" + searchData);[/align]
[align=left] }[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
使用游标来定位多重记录
Cursor.getNext(), Cursor.getPrev()
Cursor.getSearchBothRange()
Cursor.getNextNoDup(), Cursor.getPrevNoDup()
跳到上一个key的最后一个data或下一个key的第一个data,忽略 当前key多重记录的存在。
Cursor.getNextDup(), Cursor.getPrevDup()
使用示例:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] // Create DatabaseEntry objects[/align]
[align=left] // searchKey is some String.[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] OperationStatus retVal = cursor.getSearchKey(theKey,[/align]
[align=left]theData, LockMode.DEFAULT);[/align]
[align=left] [/align]
[align=left] if (cursor.count() > 1) {[/align]
[align=left] while (retVal == OperationStatus.SUCCESS) {[/align]
[align=left] String keyString = new String(theKey.getData(), "UTF-8");[/align]
[align=left] String dataString = new String(theData.getData(), "UTF-8");[/align]
[align=left] System.out.println("Key | Data : " + keyString + " | " +[/align]
[align=left] dataString + "");[/align]
[align=left] retVal = cursor.getNextDup(theKey, theData, LockMode.DEFAULT);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] // Make sure to close the cursor[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
通过游标来添加数据
Cursor.putNoDupData()
Cursor.putNoOverwrite()
[align=left] 如果存在相同的key在database里则返OperationStatus.KEYEXIS,[/align]
[align=left]package je.gettingStarted;[/align]
[align=left] [/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]String key1str = "My first string";[/align]
[align=left]String data1str = "My first data";[/align]
[align=left]String key2str = "My second string";[/align]
[align=left]String data2str = "My second data";[/align]
[align=left]String data3str = "My third data";[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] DatabaseEntry key1 = new DatabaseEntry(key1str.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry data1 = new DatabaseEntry(data1str.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry key2 = new DatabaseEntry(key2str.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry data2 = new DatabaseEntry(data2str.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry data3 = new DatabaseEntry(data3str.getBytes("UTF-8"));[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] OperationStatus retVal = cursor.put(key1, data1); // 添加成功[/align]
[align=left] retVal = cursor.put(key2, data2); // 添 加成功[/align]
[align=left] retVal = cursor.put(key2, data3); // 如 果允许多重记录则添加成功 //[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] // Make sure to close the cursor[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
使用游标来删除记录
你可以通过调用Cursor.delete().方法来删除当前游标所指向的记录。删除后如果没有移动过指针这个时候调用 Cursor.getCurrent()还是可以得到当前值的,但移动以后就不可以了。如果没有重设指针,对同一个位置多次调用删除方法,会返回 OperationStatus.KEYEMPTY状态。
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] OperationStatus retVal = cursor.getSearchKey(theKey, theData, LockMode.DEFAULT);[/align]
[align=left] if (cursor.count() == 1) {[/align]
[align=left] System.out.println("Deleting " +[/align]
[align=left] new String(theKey.getData(), "UTF-8") +[/align]
[align=left] "|" +[/align]
[align=left] new String(theData.getData(), "UTF-8"));[/align]
[align=left] cursor.delete();//删 除当前记录[/align]
[align=left] }[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] // Make sure to close the cursor[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
修改当前游标所在位置的值
可以通过Cursor.putCurrent()方法来修改,这个方法只有一个参数就是将要修改的值。这个方法不能用在多重记录。
[align=left]import com.sleepycat.je.Cursor;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]...[/align]
[align=left]Cursor cursor = null;[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry theData = new DatabaseEntry();[/align]
[align=left] cursor = myDatabase.openCursor(null, null);[/align]
[align=left] OperationStatus retVal = cursor.getSearchKey(theKey, theData,[/align]
[align=left]LockMode.DEFAULT);[/align]
[align=left] [/align]
[align=left] String replaceStr = "My replacement string";[/align]
[align=left] DatabaseEntry replacementData =[/align]
[align=left] new DatabaseEntry(replaceStr.getBytes("UTF-8"));[/align]
[align=left] cursor.putCurrent(replacementData);//把 当前位置用新值替换[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] // Make sure to close the cursor[/align]
[align=left] cursor.close();[/align]
[align=left]}[/align]
二级database
在JE中包含你需要的(主要)数据的database被叫做primary database.而通过某种关系关联起来的叫secondary database.通常secondary database和primary database的key是一样的,只不过是为了对应多条不同类型的数据。
打开和关闭二级库
你可以通过Environment.openSecondaryDatabase()这个方法来打开一个二级库,在打开前你必须指定二级库的名称和配置信 息。
需要与primary database和secondary database间绑定的就是索引。二级库通常能够提供额外的信息。
如果想要使用二级库,primary database不能支持多重记录,他的key必须得保证唯一。不然你没办法进行关联。
所以说如果你要想打开和创建一个二级库需要如下步骤
设置你的二级库的配置文件,也就是创建SecondaryConfig
使用示例如下:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseConfig;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.Environment;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]import com.sleepycat.je.SecondaryConfig;[/align]
[align=left]import java.io.File;[/align]
[align=left]...[/align]
[align=left]DatabaseConfig myDbConfig = new DatabaseConfig();[/align]
[align=left]SecondaryConfig mySecConfig = new SecondaryConfig();[/align]
[align=left]myDbConfig.setAllowCreate(true);[/align]
[align=left]mySecConfig.setAllowCreate(true);[/align]
[align=left]mySecConfig.setSortedDuplicates(true);[/align]
[align=left]// primary database[/align]
[align=left]Environment myEnv = null;[/align]
[align=left]Database myDb = null;[/align]
[align=left]SecondaryDatabase mySecDb = null;[/align]
[align=left]try {[/align]
[align=left] String dbName = "myPrimaryDatabase";[/align]
[align=left] myEnv = new Environment(new File("/tmp/JEENV"), null);[/align]
[align=left] myDb = myEnv.openDatabase(null, dbName, myDbConfig);[/align]
[align=left] TupleBinding myTupleBinding = new MyTupleBinding();[/align]
[align=left] FullNameKeyCreator keyCreator = new FullNameKeyCreator(myTupleBinding);[/align]
[align=left] mySecConfig.setKeyCreator(keyCreator);[/align]
[align=left] String secDbName = "mySecondaryDatabase";[/align]
[align=left] mySecDb = myEnv.openSecondaryDatabase(null, secDbName,[/align]
[align=left] myDb, mySecConfig);[/align]
[align=left]} catch (DatabaseException de) {[/align]
[align=left]}[/align]
可以调用二级库的close()方法来关闭一个二级库,在关闭 primary database前你必须先关闭一个二级库。
[align=left]try {[/align]
[align=left] if (mySecDb != null) {[/align]
[align=left] mySecDb.close();[/align]
[align=left] }[/align]
[align=left] if (myDb != null) {[/align]
[align=left] myDb.close();[/align]
[align=left] }[/align]
[align=left] if (myEnv != null) {[/align]
[align=left] myEnv.close();[/align]
[align=left] }[/align]
[align=left]} catch (DatabaseException dbe) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
二级库的键创建器
在使用二级库的时候,你必须提供二级库的键创建器来为二级库创建二级。在程序中你可以使用 SecondaryConfig.setKeyCreator()来指定一个键创建器。你可以使用任何的数据创建二级库的键,只要对你来说是需要的。
自定义键创建器需要继承SecondaryKeyCreator类,并且要重写其中的createSecondaryKey方法。 createSecondaryKey返回一个boolean形式的值,如果返回false,则表示二级库不存在这个key.
[align=left]package je.gettingStarted;[/align]
[align=left]public class PersonData {[/align]
[align=left] private String userID;[/align]
[align=left] private String surname;[/align]
[align=left] private String familiarName;[/align]
[align=left] public PersonData(String userID, String surname, String familiarName) {[/align]
[align=left] this.userID = userID;[/align]
[align=left] this.surname = surname;[/align]
[align=left] this.familiarName = familiarName;[/align]
[align=left] }[/align]
[align=left] public String getUserID() {[/align]
[align=left] return userID;[/align]
[align=left] }[/align]
[align=left] public String getSurname() {[/align]
[align=left] return surname;[/align]
[align=left] }[/align]
[align=left] public String getFamiliarName() {[/align]
[align=left] return familiarName;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left]import com.sleepycat.je.SecondaryKeyCreator;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]import java.io.IOException;[/align]
[align=left]public class FullNameKeyCreator implements SecondaryKeyCreator {[/align]
[align=left] private TupleBinding theBinding;[/align]
[align=left] public FullNameKeyCreator(TupleBinding theBinding1) {[/align]
[align=left] theBinding = theBinding1;[/align]
[align=left] }[/align]
[align=left] public boolean createSecondaryKey(SecondaryDatabase secDb,[/align]
[align=left] DatabaseEntry keyEntry,[/align]
[align=left] DatabaseEntry dataEntry,[/align]
[align=left] DatabaseEntry resultEntry) {[/align]
[align=left] try {[/align]
[align=left] PersonData pd =[/align]
[align=left] (PersonData) theBinding.entryToObject(dataEntry);[/align]
[align=left] String fullName = pd.getFamiliarName() + " " +[/align]
[align=left] pd.getSurname();[/align]
[align=left] resultEntry.setData(fullName.getBytes("UTF-8"));[/align]
[align=left] } catch (IOException willNeverOccur) {}[/align]
[align=left] return true;[/align]
[align=left] }[/align]
[align=left]}[/align]
然后你可以向下面的方法使用你的键创建器
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.bind.tuple.TupleBinding;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.Environment;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]import com.sleepycat.je.SecondaryConfig;[/align]
[align=left]...[/align]
[align=left]Environment myEnv = null;[/align]
[align=left]Database myDb = null;[/align]
[align=left]SecondaryDatabase mySecDb = null;[/align]
[align=left]try {[/align]
[align=left]...[/align]
[align=left] TupleBinding myDataBinding = new MyTupleBinding();[/align]
[align=left] FullNameKeyCreator fnkc = new FullNameKeyCreator(myDataBinding);[/align]
[align=left] SecondaryConfig mySecConfig = new SecondaryConfig();[/align]
[align=left] mySecConfig.setKeyCreator(fnkc);[/align]
[align=left] String secDbName = "mySecondaryDatabase";[/align]
[align=left] mySecDb = myEnv.openSecondaryDatabase(null, secDbName, myDb,[/align]
[align=left] mySecConfig);[/align]
[align=left]} catch (DatabaseException de) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]} finally {[/align]
[align=left] try {[/align]
[align=left] if (mySecDb != null) {[/align]
[align=left] mySecDb.close();[/align]
[align=left] }[/align]
[align=left] if (myDb != null) {[/align]
[align=left] myDb.close();[/align]
[align=left] }[/align]
[align=left] if (myEnv != null) {[/align]
[align=left] myEnv.close();[/align]
[align=left] }[/align]
[align=left] } catch (DatabaseException dbe) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left] }[/align]
[align=left]}[/align]
二级库的配置设置
可以通过SecondaryConfig来配置二级库,SecondaryConfig是 DatabaseConfig的子类。所以你可以使用DatabaseConfig的一些信息。
你可以通过SecondaryDatabase.get()或使用 SecondaryCursor.来读取二级库的信息。与primary database不同的是data不是直接返回给你,而是返回给你对应的primary database中的key和data和二级库中对应的key.
如果二级库支持多重记录,则只返回第一条对应的数据。如果想看其他的只能通过SecondaryCursor(二级库游标)了。
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] String searchName = "John Doe";[/align]
[align=left] DatabaseEntry searchKey =[/align]
[align=left] new DatabaseEntry(searchName.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry primaryKey = new DatabaseEntry();[/align]
[align=left] DatabaseEntry primaryData = new DatabaseEntry();[/align]
[align=left] // 通过searchKey查找primary database的key和value[/align]
[align=left] OperationStatus retVal = mySecondaryDatabase.get(null, searchKey,[/align]
[align=left]primaryKey, primaryData, LockMode.DEFAULT);[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
删除二级库的记录
通常来讲你不能够直接修改二级库的记录,而只能通过修改primary database来达到修改二级库的目的。但是你可以直接通过econdaryDatabase.delete()来删除二级库的记录。但是如果你的库支 持多重记录,那么只能删除匹配的第一条。
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] String searchName = "John Doe";[/align]
[align=left] DatabaseEntry searchKey =[/align]
[align=left] new DatabaseEntry(searchName.getBytes("UTF-8"));[/align]
[align=left] // 删除匹配JOHN DOE键的第一个二级库的记录[/align]
[align=left] OperationStatus retVal = mySecondaryDatabase.delete([/align]
[align=left]null, searchKey);[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
跟primary database一样你同样可以使用游标来操作数据。当你使用二级库游标的去记录的时候,都会包含primary的记录。 SecondaryCursor.getSearchBoth()来搜索并不是搜索key/value对,而是搜索key和primary key.
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]import com.sleepycat.je.SecondaryCursor;[/align]
[align=left]...[/align]
[align=left]try {[/align]
[align=left] ...[/align]
[align=left] String secondaryName = "John Doe";[/align]
[align=left] DatabaseEntry secondaryKey =[/align]
[align=left] new DatabaseEntry(secondaryName.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry foundData = new DatabaseEntry();[/align]
[align=left] SecondaryCursor mySecCursor =[/align]
[align=left] mySecondaryDatabase.openSecondaryCursor(null, null);[/align]
[align=left] OperationStatus retVal = mySecCursor.getSearchKey(secondaryKey,[/align]
[align=left] foundData, LockMode.DEFAULT);[/align]
[align=left] while (retVal == OperationStatus.SUCCESS) {[/align]
[align=left] mySecCursor.delete();[/align]
[align=left] retVal = mySecCursor.getNextDup(secondaryKey,[/align]
[align=left] foundData, LockMode.DEFAULT);[/align]
[align=left] }[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Exception handling goes here[/align]
[align=left]}[/align]
如果你创建了两个或两个以上的二级库,你可以通过JoinCursor.来把他们关联起来, 可以采用JoinCursor来实现多维度的查询,例如可以查询
String theColor = "red";
String theType = "minivan";
String theMake = "Toyota";
来实现直接查找这些指定数据的记录。与普通的游标比较起来是可以对data域进行查询,与单个次级数据库游标查询比较起来是可以实现多个条件的 联立查询。
通过Database.join()方法来建立关系
通过JoinCursor.getNext()方法来遍历相关记录直到 OperationStatus is not SUCCESS.为止。
使用示例:
[align=left]package je.gettingStarted;[/align]
[align=left]import com.sleepycat.je.Database;[/align]
[align=left]import com.sleepycat.je.DatabaseEntry;[/align]
[align=left]import com.sleepycat.je.DatabaseException;[/align]
[align=left]import com.sleepycat.je.JoinCursor;[/align]
[align=left]import com.sleepycat.je.LockMode;[/align]
[align=left]import com.sleepycat.je.OperationStatus;[/align]
[align=left]import com.sleepycat.je.SecondaryCursor;[/align]
[align=left]import com.sleepycat.je.SecondaryDatabase;[/align]
[align=left]...[/align]
[align=left]// Query strings:[/align]
[align=left]String theColor = "red";[/align]
[align=left]String theType = "minivan";[/align]
[align=left]String theMake = "Toyota";[/align]
[align=left]SecondaryCursor colorSecCursor = null;[/align]
[align=left]SecondaryCursor typeSecCursor = null;[/align]
[align=left]SecondaryCursor makeSecCursor = null;[/align]
[align=left]JoinCursor joinCursor = null;[/align]
[align=left]DatabaseEntry foundKey = new DatabaseEntry();[/align]
[align=left]DatabaseEntry foundData = new DatabaseEntry();[/align]
[align=left]try {[/align]
[align=left] DatabaseEntry color = new DatabaseEntry(theColor.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry type = new DatabaseEntry(theType.getBytes("UTF-8"));[/align]
[align=left] DatabaseEntry make = new DatabaseEntry(theMake.getBytes("UTF-8"));[/align]
[align=left] colorSecCursor = automotiveColorDB.openSecondaryCursor([/align]
[align=left]null, null);[/align]
[align=left] typeSecCursor = automotiveTypeDB.openSecondaryCursor([/align]
[align=left]null, null);[/align]
[align=left] makeSecCursor = automotiveMakeDB.openSecondaryCursor([/align]
[align=left]null, null);[/align]
[align=left] OperationStatus colorRet =[/align]
[align=left] colorSecCursor.getSearchKey(color, foundData, LockMode.DEFAULT);[/align]
[align=left] OperationStatus typeRet =[/align]
[align=left] typeSecCursor.getSearchKey(type, foundData, LockMode.DEFAULT);[/align]
[align=left] OperationStatus makeRet =[/align]
[align=left] makeSecCursor.getSearchKey(make, foundData, LockMode.DEFAULT);[/align]
[align=left] // If all our searches returned successfully, we can proceed[/align]
[align=left] if (colorRet == OperationStatus.SUCCESS &&[/align]
[align=left] typeRet == OperationStatus.SUCCESS &&[/align]
[align=left] makeRet == OperationStatus.SUCCESS) {[/align]
[align=left] // Get a secondary cursor array and populate it with our[/align]
[align=left] // 创建SecondaryCursor[/align]
[align=left] SecondaryCursor[] cursorArray = {colorSecCursor,[/align]
[align=left] typeSecCursor, makeSecCursor, null};[/align]
[align=left] // Create the join cursor[/align]
[align=left] joinCursor = automotiveDB.join(cursorArray, null);[/align]
[align=left] // Now iterate over the results, handling each in turn[/align]
[align=left] while (joinCursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==[/align]
[align=left] OperationStatus.SUCCESS) {[/align]
[align=left] // Do something with the key and data retrieved in[/align]
[align=left] // foundKey and foundData[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]} catch (DatabaseException dbe) {[/align]
[align=left] // Error reporting goes here[/align]
[align=left]} catch (Exception e) {[/align]
[align=left] // Error reporting goes here[/align]
[align=left]} finally {[/align]
[align=left] try {[/align]
[align=left] // Make sure to close out all our cursors[/align]
[align=left] if (colorSecCursor != null) {[/align]
[align=left] colorSecCursor.close();[/align]
[align=left] }[/align]
[align=left] if (typeSecCursor != null) {[/align]
[align=left] typeSecCursor.close();[/align]
[align=left] }[/align]
[align=left] if (makeSecCursor != null) {[/align]
[align=left] makeSecCursor.close();[/align]
[align=left] }[/align]
[align=left] if (joinCursor != null) {[/align]
[align=left] joinCursor.close();[/align]
[align=left] }[/align]
[align=left] } catch (DatabaseException dbe) {[/align]
[align=left] // Error reporting goes here[/align]
[align=left] }[/align]
[align=left]}[/align]
你可以通过JoinConfig来配置joinCursor,JoinConfig只有一个 方法。
JoinConfig.setNoSort(),如果设置为true,则表示不使用自动排序,false的时候则按照关联少的到关联多的方式排序。
[align=left]JoinConfig config = new JoinConfig();[/align]
[align=left]config.setNoSort(true);[/align]
[align=left]JoinCursor joinCursor = myDb.join(cursorArray, config);[/align]
数据的备份和恢复
在了解数据备份和恢复前你有必要了解下JE database的内部数据结构、日志文件 和内存CACHE。
JE以追加的方式向日志文件中添加数据,这意味着你日志文件永远不会被覆盖, 修改和删除。日志文件的命名是NNNNNNNN.jdb,NNNNNNNN是八进制的数字,第 一个日志文件名是00000000.jdb,以后每增加一个则加一。每个日志文件的最大大小默认 是10000000 bytes ,当日志文件超过这个大小后就会在生成一个日志文件,但你可以通 过修改je.log.fileMax来修改默认的日志文件的大小。
因为JE使用不覆盖的方式来写日志文件,所以过一段时间必须得清理或压缩下日 志文件用来释放更多的磁盘空间。JE使用后台线程来清理任务。如果这个日志文件已 经不在使用,那么清理器就会自动帮你删除或给你加个删除标记。
JE databases采用BTree的方式组织,当记录被添加、修改或删除,实际上这些操 作都是控制BTree的子节点,比如说更改一个节点到另外一个父节点下。
数据库修改和同步,当对数据进行操作的时候,操作是直接操作内存中的BTree 子节点的,如果你的database不支持事务,则cache是唯一的,以保证相互间的修改不 会产生冲突。这种不时时把数据同步到磁盘其实是比较好的,因为他减少了频繁的IO 读取,从而提高了速度。但是如果你的数据要求十时性很强,你可以手动调用 Environment.sync()来时时的把数据同步到你的磁盘中,但这样可能会带来IO的繁忙。
你可以选择热备份和冷备份两种,但他都数据完全备份(也就是说所有的数据), 所以说不要把冷热备份与完全备份和增量备份相混淆。
所谓的热备份就是在你的程序还在运行的时候把所有的*.jdb文件COPY出去,这 这样的好处是你不必停止你的服务。但这样当前CACHE在内存中的数据还没有被备份 下来。
离线备份比较完全,但他的缺点也是显而易见的,你必须终止你的服务。首先你要 终止你的写操作,然后调用Environment.sync()方法来把你内存中的数据同步 到硬盘中去,关闭你的游标,你的数据库,你的环境,这个时候把所有的.jdb 文件COPY出去就行了。
[align=left]package je.gettingStarted;[/align]
[align=left]...[/align]
[align=left]import com.sleepycat.je.util.DbBackup;[/align]
[align=left]...[/align]
[align=left] Environment env = new Environment(...);[/align]
[align=left] DbBackup backupHelper = new DbBackup(env);[/align]
[align=left] long lastFileCopiedInPrevBackup = ...[/align]
[align=left] backupHelper.startBackup();[/align]
[align=left] try {[/align]
[align=left] String[] filesForBackup =[/align]
[align=left]backupHelper.getLogFilesInBackupSet(lastFileCopiedInPrevBackup);[/align]
[align=left] myApplicationCopyMethod(filesForBackup)[/align]
[align=left] lastFileCopiedInPrevBackup = backupHelper.getLastFileInBackupSet();[/align]
[align=left] myApplicationSaveLastFile(lastFileCopiedInBackupSet);[/align]
[align=left] }[/align]
[align=left] finally {[/align]
[align=left] // Remember to exit backup mode, or all log files won't be cleaned[/align]
[align=left] // and disk usage will bloat.[/align]
[align=left] backupHelper.endBackup();[/align]
[align=left] }[/align]
如果你是backup的增量方式备份你的环境目录,请COPY最新的哪个版本(翻译 的不是十分准确原文如下:If you are using a backup utility that runs incremental backups of your environment directory, copy any log files generated since the time of your last full
backup. Be sure to restore all log files in the order that they were written. The order is important because it is possible the same log file appears in multiple archives, and you want to run recovery using the most recent version of each log file)
从你的环境中复制所有的.jdb文件到你想要备份的地方,不管是热备份还是离线备份 都要这么做。在备份前要确保你把内存中的数据也同步到了磁盘中去了。这个阶段属于完全备份。
BDB针对应用的一些管理
用je.properties来 初始化一些配置信息
je.properties必须位于你环境的主目录下,且名称必须是je.properties.
je.cleaner.minUtilization
主要是用来确保腾出一定的空间来存放记录。如果空间不够用了则移出一些旧的不在使用的记录,默认这个 空间占50%。
主要是用来确认一个日志文件是否已经没用,可以被删除了,如果一个日志由原先的 NNNNNNNN.jdb 名称被修改为NNNNNNNN.del名称那么你要对这进行一些处理。
Sizing the Cache内 存中CACHE大小的设置
je.maxMemoryPercent属性来改变je能够使用的最大内存的占整个JVM虚拟机内存的百分比。
你也可以通过调用EnvironmentStats.getNCacheMiss()来取得当前有多少数据没有通过内存的方式来命中。
–r :这个操作通过不同的排序方式输出一些经过整理的那些有用的数据数据,通常如果指定你的数据库名为dbname,则他会把结果输出到 dbname.dump(翻译的不是太准确原文如下:Salvage data from a possibly corrupt file. When used on a uncorrupted database, this option should return data equivalent
to a normal dump, but most likely in a different order. This option causes the ensuing output to go to a file named dbname.dump where dbname is the name of the database you are dumping. The file is placed in the current working directory.)
–R :跟-r有所不同,他输出的是所有的数据包括被删除的和没有被删除的(原文如下:Aggressively salvage data from a possibly corrupt file. This option differs from the -r option in that it will return all possible data from the file at the risk of also
returning already deleted or otherwise nonsensical items. Data dumped in this fashion will almost certainly have to be edited by hand or other means before the data is ready for reload into another database. This option causes the ensuing output to go to a
file named dbname.dump where dbname is the name of the database you are dumping. The file is placed in the current working directory.)
使用示例:
[align=left]> java com.sleepycat.je.util.DbDump -h . -p -s VendorDB [/align]
[align=left]VERSION=3[/align]
[align=left]format=print[/align]
[align=left]type=btree[/align]
[align=left]database=VendorDB[/align]
[align=left]dupsort=false[/align]
[align=left]HEADER=END[/align]
[align=left] Mom's Kitchen[/align]
[align=left] sr\01\01xpt\00\0d53 Yerman Ct.t\00\0c763 554 9200t\00\0bMiddle Townt\00[/align]
[align=left] \0eMaggie Kultgent\00\10763 554 9200 x12t\00\02MNt\00\0dMom's Kitchent\00[/align]
[align=left] \0555432[/align]
[align=left] Off the Vine[/align]
[align=left] sr\01\01xpt\00\10133 American Ct.t\00\0c563 121 3800t\00\0aCentennialt\00[/align]
[align=left] \08Bob Kingt\00\10563 121 3800 x54t\00\02IAt\00\0cOff the Vinet\00\0552002[/align]
[align=left] Simply Fresh[/align]
[align=left] sr\01\01xpt\00\1115612 Bogart Lanet\00\0c420 333 3912t\00\08Harrigant\00[/align]
[align=left] \0fCheryl Swedbergt\00\0c420 333 3952t\00\02WIt\00\0cSimply Fresht\00\0[/align]
[align=left] 553704[/align]
[align=left] The Baking Pan[/align]
[align=left] sr\01\01xpt\00\0e1415 53rd Ave.t\00\0c320 442 2277t\00\07Dutchint\00\09[/align]
[align=left] Mike Roant\00\0c320 442 6879t\00\02MNt\00\0eThe Baking Pant\00\0556304[/align]
[align=left] The Pantry[/align]
[align=left] sr\01\01xpt\00\111206 N. Creek Wayt\00\0c763 555 3391t\00\0bMiddle Town[/align]
[align=left] t\00\0fSully Beckstromt\00\0c763 555 3391t\00\02MNt\00\0aThe Pantryt\00[/align]
[align=left] \0555432[/align]
[align=left] TriCounty Produce[/align]
[align=left] sr\01\01xpt\00\12309 S. Main Streett\00\0c763 555 5761t\00\0bMiddle Townt[/align]
[align=left] \00\0dMort Dufresnet\00\0c763 555 5765t\00\02MNt\00\11TriCounty Producet[/align]
[align=left] \00\0555432[/align]
[align=left]DATA=END[/align]
[align=left]>[/align]
使用示例:
[align=left]> java com.sleepycat.je.util.DbDump -h . -s VendorDB -f vendordb.txt[/align]
[align=left]> java com.sleepycat.je.util.DbLoad -h . -f vendordb.txt[/align]
[align=left]>[/align]
[align=left]> java com.sleepycat.je.util.DbVerify -h . -s VendorDB[/align]
[align=left]<BtreeStats>[/align]
[align=left]<BottomInternalNodesByLevel total="1">[/align]
[align=left] <Item level="1" count="1"/>[/align]
[align=left]</BottomInternalNodesByLevel>[/align]
[align=left]<InternalNodesByLevel total="1">[/align]
[align=left] <Item level="2" count="1"/>[/align]
[align=left]</InternalNodesByLevel>[/align]
[align=left]<LeafNodes count="6"/>[/align]
[align=left]<DeletedLeafNodes count="0"/>[/align]
[align=left]<DuplicateCountLeafNodes count="0"/>[/align]
[align=left]<MainTreeMaxDepth depth="2"/>[/align]
[align=left]<DuplicateTreeMaxDepth depth="0"/>[/align]
[align=left]</BtreeStats>[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: