`
mengyang
  • 浏览: 263612 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

BerkeleyDB-JE 使用BaseAPI(三)

    博客分类:
  • BDB
 
阅读更多
本篇开始介绍BIND APIs
我们已经知道,要想在JE中读写数据,必须借助DatabaseEntry对象,而原始数据和DatabaseEntry对象之间的转换,实际上要做的就是把数据转化为字节数组或者是把字节数组组装成数据。除了String类型和布尔型的数据,要进行这样的转换则必须使用JE中的BIND APIs。
可以使用BIND APIs的数据基本上分为三种:
  • 简单类型的数据
  • 实现了serialization接口的复杂类型数据
  • 没有实现serialization接口的复杂类型数据

以上三种数据使用BIND APIs的方式是各不相同的。
一.简单类型的数据
简单类型的数据包括了:String,Character,Boolean,Byte,Short,Integer,Long,Float,Double。要想把这类型的数据存储到DatabaseEntry,有两个步骤:
1.使用TupleBinding.getPrimitiveBinding返回一个可以转化相应类型的EntryBinding对象。
2.使用得到的EntryBinding对象把数据放到DatabaseEntry中。
下面演示这个过程
try {
    String aKey = "myLong";
    DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));    

    Long myLong = new Long(123456789l);
    DatabaseEntry theData = new DatabaseEntry();
    EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);
    myBinding.objectToEntry(myLong, theData);

    myDatabase.put(null, theKey, theData);
} catch (Exception e) {
    
}

要想从DatabaseEntry中获得数据也要借助EntryBinding对象
try {
    String aKey = "myLong";
    DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
    
    DatabaseEntry theData = new DatabaseEntry();
    EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);

    if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
        Long theLong = (Long) myBinding.entryToObject(theData);
        retKey = new String(theKey.getData(), "UTF-8");
        System.out.println("For key: '" + retKey + "' found Long: '" + theLong + "'.");
    } 
} catch (Exception e) {
    
}

二.实现了serialization接口的复杂类型数据
在实际使用中,像上面那个例子中的数据库里的记录-键和值都只是一个简单类型的字段的情况是很少见的。更常见的是我们会使用复杂类型的对象,它里面封装了多个字段。如果这个复杂类型对象实现了serialization接口,我们要把这个数据转入转出字节数组,我们可以使用序列化方法(Java serialization),但是这样不好,最主要的原因是如果这样做你会存储非常多无用的信息到JE中。所以我们要使用BIND APIs执行序列化,并且使用BIND APIs仍然会得到序列化对象的所有好处。
使用BIND APIs执行序列化的步骤如下:
1.首先你要读写的类必须实现serialization接口。
2.打开两个database,一个用于保存要读写的数据,另外一个用于保存数据的类型信息。
3.创建StoredClassCatalog对象,这个对象代表了一个类型目录,它需要传入保存数据的类型信息的数据库。
4.创建EntryBinding对象,它需要传入StoredClassCatalog对象和序列化对象的类信息。
5.使用SerialBinding对象把数据放到DatabaseEntry
下面演示这个过程,首先是你要保存到JE的类
public class MyData implements Serializable {
    private long longData;
    private double doubleData;
    private String description;
    //省略get和set方法...
}

接下去是你要序列化的方法:
String aKey = "myData";
MyData data2Store = new MyData();
data2Store.setLong(123456789l);
data2Store.setDouble(1234.9876543);
data2Store.setDescription("A test instance of this class");
try {
    DatabaseConfig myDbConfig = new DatabaseConfig();
    myDbConfig.setAllowCreate(true);
    Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);
    Database myClassDb = myDbEnv.openDatabase(null, "classDb", 
                                              myDbConfig); 

    StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);
    EntryBinding dataBinding = new SerialBinding(classCatalog, 
                                                 MyData.class);

    DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
    DatabaseEntry theData = new DatabaseEntry();
    dataBinding.objectToEntry(data2Store, theData);

    myDatabase.put(null, theKey, theData);
} catch (Exception e) {

}

下面演示反序列化
String aKey = "myData";
try {
    DatabaseConfig myDbConfig = new DatabaseConfig();
    myDbConfig.setAllowCreate(false);
    Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);
    Database myClassDb = myDbEnv.openDatabase(null, "classDb", 
                                              myDbConfig); 
    StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);
    EntryBinding dataBinding = new SerialBinding(classCatalog, 
                                                 MyData.class);
    DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
    DatabaseEntry theData = new DatabaseEntry();
    myDatabase.get(null, theKey, theData, LockMode.DEFAULT);
    MyData retrievedData = (MyData) dataBinding.entryToObject(theData);
 
} catch (Exception e) {

}

三.没有实现serialization接口的复杂类型数据
我们使用自定义的元组绑定(Custom Tuple Bindings)来转换这类型的数据。必须首先说明的是对于任何类型的数据,包括实现了serialization接口类型的数据仍然可以使用这种方法。而且按照官方文档上的说明,是推荐对任何复杂类型数据都使用这种方法的。它有以下的优点:
  • 支持排序,通过序列化得到的字节数组的顺序是没有意义的
  • 压缩数据量,比序列化得到的字节数组大小上小很多
  • 加速原始数据和字节数组的转换过程,比序列化转换来的快
  • 可以使用自定的比较器,使用序列化绑定的方法是无法使用自定义比较器的

使用的步骤有:
1.编写你需要读写到JE的类,它可以不用实现serialization接口
2.使用TupleBinding类新建一个元组绑定器(tuple binding)
3.打开数据(只要一个就好)
4.使用你新建的元组绑定器(tuple binding)创建EntryBinding对象
5.使用EntryBinding对象把数据放到DatabaseEntry
下面给出演示:
首先是要读写到JE的类
public class MyData2 {
    private long longData;
    private double doubleData;
    private String description;
    //省略get和set方法...
}

然后你要必须为这个类创建一个元组绑定器(tuple binding),你必须继承TupleBinding类,然后实现两个抽象方法:TupleBinding.objectToEntry() and TupleBinding.entryToObject()。同时有几点你要注意:
  • 使用objectToEntry()方法转换对象到字节数组。你可以使用TupleOutput转化原始类型的数据。使用的时候要注意对数值型数据的处理,它只能接受原始类型的数据(比如long, double, int...),而不能处理它们的封装类型(比如Long, Double, Integer...)。
  • 你使用objectToEntry()方法转化对象中每个字段的顺序关系到对字节数组的排序,以上面的MyData2类为例,如果转化的顺序是longData,doubleData,description,那么得到的字节数组就会先按顺序的保存这些成员变量,这也意味着你的记录将先按longData的值来排序,而后是doubleData,最后是description。如果你想按doubleData来排序,那你就必须首先转化这个成员变量。
  • 使用entryToObject()方法转换字节数组到对象。你可以使用TupleInput来执行这个转换。
  • 从字节数组中读取成员变量的顺序必须跟你转化成员变量到字节数组的顺序一致。

public class MyTupleBinding extends TupleBinding {
// 转换对象到字节数组
public void objectToEntry(Object object, TupleOutput to) {
MyData2 myData = (MyData2)object;
to.writeDouble(myData.getDouble().doubleValue());
to.writeLong(myData.getLong());
to.writeString(myData.getString());
}
// 转换字节数组为对象
public Object entryToObject(TupleInput ti) {
Double theDouble = new Double(ti.readDouble());
long theLong = ti.readLong();
String theString = ti.readString();
MyData2 myData = new MyData2();
myData.setDouble(theDouble);
myData.setLong(theLong);
myData.setString(theString);
return myData;
}
}

最后你就可以读写数据了
TupleBinding keyBinding = new MyTupleBinding();
MyData2 theKeyData = new MyData2();

theKeyData.setLong(123456789l);
theKeyData.setDouble(new Double(12345.6789));
theKeyData.setString("My key data");
DatabaseEntry myKey = new DatabaseEntry();
try {
// Store theKeyData in the DatabaseEntry
keyBinding.objectToEntry(theKeyData, myKey);
...
// Database put and get activity omitted for clarity
...
// Retrieve the key data
theKeyData = (MyData2) keyBinding.entryToObject(myKey);
} catch (Exception e) {
// Exception handling goes here
}
0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics