读书人

BerkeleyDB-JE 应用BaseAPI(七)

发布时间: 2012-12-26 14:39:29 作者: rapoo

BerkeleyDB-JE 使用BaseAPI(七)
本篇开始介绍二级数据库(Secondary Databases)的使用。

通常情况下,我们根据key值来查找JE中的记录,但是key值不一定会包含你所要想要查询的值,比如JE中有个用户库,你使用一个唯一的没有什么意义的ID作为key值,而data值是一个复杂的java对象,它封装了用户名,性别,生日,年龄等信息,如果你想查找某个具有某个名字的用户记录,那么你可能要遍历整个数据库。这时候JE还提供了一个选择,就是使用Secondary Databases。

在这里Secondary Databases可以使你创建一个基于用户名的索引,这样你就可以使用这个索引进行查询。在JE中,包含了你想要的数据的数据库叫做主数据库(Primary Database),而包含了可选的key集合的用于访问Primary database中数据的数据库称为二级数据库(Secondary Databases)。

一旦你打开了一个Secondary Databases,JE会为你管理其中的数据。当你添加或者删除Primary Database中记录的时候,JE会自动对Secondary Databases中的数据作出必要的修改;当你修改了Primary Database中的记录,并且这个修改会导致Secondary Databases中的key发生变化的时候,JE也会调整Secondary Databases。

一定要注意一点,你不能直接对Secondary Databases中的数据进行操作,虽然其中存在这样的API,但是如果你调用了这些API,则会报出异常。唯一的例外是你可以删除Secondary Databases中的数据。

当你从Secondary Databases中获取记录值的时候,实际上返回的是对应在Primary Database中的记录。

下面开始讲解如何打开和关闭Secondary Databases,有5个步骤:
1.打开Primary Database
2.实例化SecondaryKeyCreator对象
3.实例化SecondaryConfig对象
4.为SecondaryConfig设置SecondaryKeyCreator对象
5.用Primary Database和SecondaryConfig打开Secondary Databases

相比打开普通的Database,要打开Secondary Database,这里最大的区别就在于多了个SecondaryKeyCreator对象。这个对象是用来创建你想要的索引的。你能使用任何数据来创建key,一般情况下,你会使用Primary Database中的data值来创建这个key,当然你也可以使用Primary Database的key值。

为此,你要实现SecondaryKeyCreator接口,这个接口要求你实现SecondaryKeyCreator.createSecondaryKey() 方法。有一点要注意的是,你要抽取的key值是来自于保存于Primary Database中的记录,而在JE中,一条记录键和值都是DatabaseEntry类型的,而且在这个方法中你要生成的key最终也要表现成DatabaseEntry形式,所以你可能需要依赖于Binding API,比如在你使用复杂对象的时候。这个方法的返回值是一个boolean,如果返回false,则说明不存在二级键,这就意味着Primary Database不会填充数据到Secondary Databases中,如果该Secondary Databases有记录,则会被删除。

下面演示下这个过程:
首先假设,我们有个数据库,名叫myPrimaryDatabase,里面存储的记录值是PersonData类型数据,key值是String,同时还有了个自定义的Binding:TupleBinding

public class FullNameKeyCreator implements SecondaryKeyCreator {     private TupleBinding theBinding;    public FullNameKeyCreator(TupleBinding theBinding1) {            theBinding = theBinding1;    }    public boolean createSecondaryKey(SecondaryDatabase secDb,                                      DatabaseEntry keyEntry,                                       DatabaseEntry dataEntry,                                      DatabaseEntry resultEntry) {        try {            PersonData pd = (PersonData) theBinding.entryToObject(dataEntry);            String fullName = pd.getFamiliarName() + " " + pd.getSurname();            resultEntry.setData(fullName.getBytes("UTF-8"));        } catch (IOException willNeverOccur) {}        return true;    }}

然后我们这样打开和关闭Secondary Datab
DatabaseConfig myDbConfig = new DatabaseConfig();SecondaryConfig mySecConfig = new SecondaryConfig();myDbConfig.setAllowCreate(true);mySecConfig.setAllowCreate(true);mySecConfig.setSortedDuplicates(true);Environment myEnv = null;Database myDb = null;SecondaryDatabase mySecDb = null;try {    String dbName = "myPrimaryDatabase";    myEnv = new Environment(new File("/tmp/JEENV"), null);    myDb = myEnv.openDatabase(null, dbName, myDbConfig);    TupleBinding myTupleBinding = new MyTupleBinding();    FullNameKeyCreator keyCreator =         new FullNameKeyCreator(myTupleBinding);    mySecConfig.setKeyCreator(keyCreator);    String secDbName = "mySecondaryDatabase";    mySecDb = myEnv.openSecondaryDatabase(null, secDbName, myDb,                                           mySecConfig); } catch (DatabaseException de) {}finally {    //close的顺序要注意下    try {        if (mySecDb != null) {            mySecDb.close();        }        if (myDb != null) {            myDb.close();                 }        if (myEnv != null) {            myEnv.close();        }    } catch (DatabaseException dbe) {    }}

SecondaryConfig是DatabaseConfig的子类,你可以像设置DatabaseConfig一样设置它。这里有一个属性说明下:
SecondaryConfig.setAllowPopulate():设置为Secondary Databases是否可以自动填充。是指当Secondary Databases为空的时候,在Primary Databases只读的时候,Secondary Databases中的记录会被自动的添加或修改。(This means that on open, if the secondary database is empty then the primary database is read in its entirety and additions/modifications to the secondary's records occur automatically.)

读书人网 >其他数据库

热点推荐