这里简单再介绍下Berkeley的二级数据库的知识,
最近没怎么接触又忘了,本来是在想,这个数据库是基于内存的,那持久化问题怎么解决呢?是否有什么API可以实现存储到磁盘上呢?后来发现,其实BerkeleyDB已经为我们实现了自动存储,只需要我们正确close(),数据就会存储起来了,于是乎,就再看看二级数据库。。
二级数据库的来源:
Usually you find database records by means of the record's key. However, the key that you use for your record will not always contain the information required to provide you with rapid access to the data that you want to retrieve. For example, suppose your Database contains records related to users. The key might be a string that is some unique identifier for the person, such as a user ID. Each record's data, however, would likely contain a complex object containing details about people such as names, addresses, phone numbers, and so forth. While your application may frequently want to query a person by user ID (that is, by the information stored in the key), it may also on occasion want to locate people by, say, their name.
例如我们现在有Student这个类,我们之前都是通过id来进行索引,这个不方便的地方就是如果我们想找Jimmy,怎么实现呢?过去我们可以通过遍历,一个个比较name==Jimmy,相等则返回结果。
In JE, the Database
that contains your data is called a primary database. A database that provides an alternative set of keys to access that data is called a secondary database,
二级索引则帮助我们改善了上述做法,具体实现我也不是很清楚,还是得看源码,不过下面我会给大家说下我的一些想法。
其实建立这个二级索引并不是很难,大家就想象成再次建立一个数据库罢了,只不过这个数据库的Key需要我们自己定义,这就是为什么它能够根据这个索引来定位Primary数据库的记录。
Primary databases must not support duplicate records.
Secondary records point to primary records using the primary key, so that key must be unique.
So to open (create) a secondary database, you:
Open your primary database.
Instantiate your key creator.
Instantiate your SecondaryConfig
object.
Set your key creator object on your SecondaryConfig
object.
Open your secondary database, specifying your primary database and your SecondaryConfig
at that time.
这里的KeyCreator就是我们自己为二级索引库建立索引,正如Primary的索引也是我们自己定义的数据类型,这里二级索引只不过是让我们提供另一个我们也希望可以查询数据用的索引。
这样理解就简单了,如果我们希望通过Student的name来查找学生,那我们需要自己实现一个KeyCreator的类来实现这个Key对象的生成,并且把它交给二级索引
这个Key生成器的类实现必须实现SecondaryKeyCreator的接口,同时实现里面的方法
class KeyCreator implements SecondaryKeyCreator{ private EntryBinding valueBinding = null; public KeyCreator(EntryBinding binding) { valueBinding = binding;//用来实现Entry--object 转换 } @Override public boolean createSecondaryKey(SecondaryDatabase sdb, DatabaseEntry keyEntry, DatabaseEntry valueEntry, DatabaseEntry resultEntry) { V value = (V)valueBinding.entryToObject(valueEntry); String data = value.toString(); System.out.println("in createSKey..."+data); try { resultEntry.setData(data.getBytes(charset)); return true; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return false; } }可以看到,我这里建立的二级索引用的是toString()这个字符串来对数据进行另一中途径的索引。
实现了我们自己的索引key之后,剩下就是和主数据库创建过程一样了
/** * 创建二级索引数据库 */ String secDbName = "secDbName"; secCfig = new SecondaryConfig(); secCfig.setAllowCreate(true); secCfig.setSortedDuplicates(true);//二级库可以有重复 KeyCreator keyCreator = new KeyCreator(valueBinding); secCfig.setKeyCreator(keyCreator); secDb = env.openSecondaryDatabase(null, secDbName, db, secCfig);
java之BerkeleyDB(二)--绑定(Binding)技术、游标(Cursor)
这个二级索引库的使用方法见如下所示,同样也可以采用cursor游标,这些都和主数据库一致的,大家注意下,我们是不可以通过二级库来修改主数据库的内容,只能删除,不能更改!!
/** * 查找 */ public V getBySec(String searchContent){ try{ DatabaseEntry searchEntry = new DatabaseEntry(searchContent.getBytes(charset)); DatabaseEntry keyEntry = new DatabaseEntry(); DatabaseEntry valueEntry = new DatabaseEntry(); secDb.get(null, searchEntry, keyEntry, valueEntry, LockMode.DEFAULT); if(valueEntry.getData()!=null){ V value = (V)valueBinding.entryToObject(valueEntry); return value; } }catch(Exception e){ e.printStackTrace(); } return null; }
public static void main(String[] args) { BDBUtil<Integer, Student> bDB = new BDBUtil<Integer, Student>("testDB",Student.class); Student s1 = new Student(1,"ylf"); BDBIterator it = bDB.getIterator(); while(it.hasNext()){ Student t = (Student)it.currentValue(); System.out.println(it.currentKey()+t.toString()); } it.close(); String searchContent = s1.toString(); Student find = bDB.getBySec(searchContent); if(find != null) System.out.println("find:"+find.toString()); bDB.close(); }
1 Student1:ylf 2 Student2:dsb 3 Student3:dbc 4 Student1:ylf 5 Student5:zjq 6 Student6:zjq 7 Student3:dbc Find:Student1:ylf
String searchContent = s2.toString(); Student find = bDB.getBySec(searchContent);
insert a new Student: in createSKey...Student9:Jimmy insert OK, now find him by secDB: Find:Student9:Jimmy
System.out.println("insert a new Student:"); Student s9 = new Student(9,"Jimmy"); bDB.put(9, s9); System.out.println("insert OK, now find him by secDB:"); String searchContent = s9.toString(); Student find = bDB.getBySec(searchContent); if(find != null) System.out.println("Find:"+find.toString());
in createSKey...Student9:Jimmy这句是在接口方法 createSecondaryKey()里打印出来的,这个过程和上面的猜想基本符合的,我也不是想说明什么问题,只是这种理解方便我自己理解罢了,如果有问题大家多多交流交流