转自:http://blog.csdn.net/ylf13/article/details/15337957
有几个注意的,在BDB数据库里,默认是不能有重复的两个相同的键,当然可以通过config配置sortedDupli...来设置可以,所以在读取数据库值的时候必须考虑两种情况,是否存在相同的键的记录
JE provides two basic mechanisms for the storage and retrieval of database key/data pairs:
-
The
Database.put()
andDatabase.get()
methods provide the easiest access for all non-duplicate records in the database. These methods are described in this section. -
Cursors provide several methods for putting and getting database records. Cursors and their database access methods are described inUsing Cursors.
-
Database.put()
-
Database.putNoOverwrite()
-
Database.putNoDupData()
-
Database.get() 这个利用key来找
-
Database.getSearchBoth() 这个利用Key和value共同找记录
上篇我们简单的打开了数据库和进行简单的存储
这个对于我们存储数据的基本类型还行,但是涉及到用户自定义类的时候,单靠之前的转换函数来从string转换程对象是不妨便的,我们来看看BDB为我们准备来什么?
引自使用手册:
DatabaseEntry
can hold any kind of data from simple Java primitive types to complex Java objects so long as that data can be represented as a Javabyte
array. Note that due to performance considerations,you should not use Java serialization to convert a Java object to abyte
array. Instead, use the Bind APIs to perform this conversion(seeUsing the BIND APIsfor more information).
看到加粗这段了把,官方推荐我们用Bind
(一)Bind技术
(1)SeriaBinding
先说下序列化的绑定技术,言外之意,我们的数据类型就必须实现Serializable才能进行下面的绑定
Serializing Objects
To store a serializable complex object using the Bind APIs:
-
Implement java.io.Serializable in the class whose instances that you want to store.
-
Open (create) your databases. You need two. The first is the database that you use to store your data. The second is used to store the class information.
-
Instantiate a class catalog. You do this with
com.sleepycat.bind.serial.StoredClassCatalog
, and at that time you must provide a handle to an open database that is used to store the class information. -
Create an entry binding that uses
com.sleepycat.bind.serial.SerialBinding
. -
Instantiate an instance of the object that you want to store, and place it in a
DatabaseEntry
using the entry binding that you created in the previous step.
没看源码,也没什么好展开的,大家就把方法记着吧,以后再一步步来
由于需要用到Class这个类,所以构造函数多了一个value的Class
这样就可以使得我们自己数据完整的存入了
- importjava.io.File;
- importjava.io.Serializable;
- importjava.io.UnsupportedEncodingException;
- importcom.sleepycat.bind.EntryBinding;
- importcom.sleepycat.bind.serial.SerialBinding;
- importcom.sleepycat.bind.serial.StoredClassCatalog;
- importcom.sleepycat.bind.serial.TupleSerialBinding;
- importcom.sleepycat.bind.tuple.TupleBase;
- importcom.sleepycat.bind.tuple.TupleBinding;
- importcom.sleepycat.bind.tuple.TupleTupleBinding;
- importcom.sleepycat.je.Database;
- importcom.sleepycat.je.DatabaseConfig;
- importcom.sleepycat.je.DatabaseEntry;
- importcom.sleepycat.je.Environment;
- importcom.sleepycat.je.EnvironmentConfig;
- importcom.sleepycat.je.LockMode;
- importcom.sleepycat.je.OperationStatus;
- publicclassMain{
- /**
- *@paramargs
- */
- staticEnvironmentenv=null;
- publicstaticvoidmain(String[]args){
- BDBUtil<Integer,Student>bDB=newBDBUtil<Integer,Student>("testDB",Student.class);
- Students1=newStudent(1,"ylf");
- Students2=newStudent(2,"dsb");
- Students3=newStudent(3,"dbc");
- bDB.put(1,s1);
- bDB.put(2,s2);
- bDB.put(3,s3);
- Students=bDB.get(3);
- System.out.println("mynameis"+s.getName()+"nois"+s.getNo());
- System.out.println(bDB.size());
- bDB.close();
- }
- }
- /**
- *我们的BDB工具
- *目前对外提供添加数据和取得数据,删除数据3个接口
- *类似HashMap的使用方法
- *注意:
- *这里的K和V两个类都必须实现来Serializable
- *而且也实现来toString
- *使用结束记得调用close()
- *@authorylf
- *
- *版本2:
- *采用动态的数据类型绑定,不是利用我们的toString()来转换对象和Entry
- *用到EntryBinding和StoredClassCatalog
- *以及binding.OnjectToEntry()EntryToObject()
- *
- */
- classBDBUtil<K,V>{
- privateEnvironmentenv=null;
- privateEnvironmentConfigenvCfig=null;
- privateDatabasedb=null;
- privateDatabaseConfigdbCfig=null;
- privateDatabaseclassDB=null;
- privateStoredClassCatalogclassCatalog=null;
- privateEntryBindingvalueBinding=null;
- privateFilefile=null;
- publicBDBUtil(StringdbName,ClassvalueClass){
- envCfig=newEnvironmentConfig();
- envCfig.setAllowCreate(true);
- file=newFile("./test/");
- env=newEnvironment(file,envCfig);
- dbCfig=newDatabaseConfig();
- dbCfig.setAllowCreate(true);
- db=env.openDatabase(null,dbName,dbCfig);
- //首先创建一个我们类的数据库
- classDB=env.openDatabase(null,"classDB",dbCfig);
- //实例化一个Catalog
- classCatalog=newStoredClassCatalog(classDB);
- //实例化一个binding来转换
- valueBinding=newSerialBinding(classCatalog,valueClass);
- }
- publicbooleanput(Kkey,Vvalue){
- DatabaseEntrykeyEntry=newDatabaseEntry(key.toString().getBytes());
- DatabaseEntryvalueEntry=newDatabaseEntry();
- valueBinding.objectToEntry(value,valueEntry);
- db.put(null,keyEntry,valueEntry);
- returntrue;
- }
- publicVget(Kkey){
- DatabaseEntrykeyEntry;
- Vvalue=null;
- try{
- keyEntry=newDatabaseEntry(key.toString().getBytes("gb2312"));
- DatabaseEntryvalueEntry=newDatabaseEntry();
- if(db.get(null,keyEntry,valueEntry,LockMode.DEFAULT)==OperationStatus.SUCCESS){
- value=(V)valueBinding.entryToObject(valueEntry);
- returnvalue;
- }
- }catch(UnsupportedEncodingExceptione){
- e.printStackTrace();
- }
- returnvalue;
- }
- publicbooleandel(KkeyStr){
- DatabaseEntrykey;
- try{
- key=newDatabaseEntry(keyStr.toString().getBytes("gb2312"));
- if(OperationStatus.SUCCESS==db.delete(null,key))
- returntrue;
- }catch(UnsupportedEncodingExceptione){
- e.printStackTrace();
- }
- returnfalse;
- }
- publiclongsize(){
- returndb.count();
- }
- publicvoidclose(){
- db.close();
- classDB.close();
- env.cleanLog();
- env.close();
- }
- }
- /**
- *序列化了的类
- *实现toString()
- *@authorylf
- *
- */
- classStudentimplementsSerializable{
- /**
- *
- */
- privatestaticfinallongserialVersionUID=7333239714054069867L;
- privateStringname;
- privateintno;
- publicStudent(){
- }
- publicStudent(intno,Stringname){
- this.no=no;
- this.name=name;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicintgetNo(){
- returnno;
- }
- publicvoidsetNo(intno){
- this.no=no;
- }
- @Override
- publicStringtoString(){
- return"Student"+no+":"+name;
- }
- publicvoidfromString(Stringstr){
- inti=str.indexOf(':');
- StringnoStr=str.substring(7,i);
- this.no=Integer.parseInt(noStr);
- this.name=str.substring(i+1);
- }
- }
- mynameisdbcnois3
- 3
(2)自定义绑定
官方还推荐使用custom tuple binding
就是我们实现TupleBinding,实现里面的objectToEntry() EntryToObject()
这里就不需要维护第二个数据库了,有木有又回到远点的赶脚!!
还不如上一篇里直接在类里实现转换
只不过官方推荐的这种是用字节流来存储,省流量,我们类里也可以利用ArrayByteInputStream好像是这个。。。我忘了,就字节流来实现就好了
(二)游标cursor
游标操作类似数据库的游标。
这里通过getNext() getPrev()来实现遍历
同时,cursor还提供了查找和插入数据的功能,我这里就不再一一写出来了,具体用到的时候在设计吧,现在全部封装一遍也不见得很好。。
- interfaceBDBIterator{
- publicObjectcurrentValue();
- publicObjectcurrentKey();
- publicbooleanhasNext();
- publicbooleanhasPrev();
- publicvoidclose();
- }
这里迭代器实现的是BDBUtil的内部类,迭代器的实现大家可以参考Java的迭代器实现方法。
- publicBDBIteratorgetIterator(){
- IteratorImplit=newIteratorImpl();
- returnit;
- }
- /**
- *这个内部类模拟iterator遍历器
- *@authorylf
- *迭代器使用方法
- *首先利用BDBUtil获得迭代器
- *hasNext()如果下一个元素存在,游标下移动,值通过currentKeycurrentValue获取
- *hasPrev()向前移动
- *最后记得close()虽然我这里已经通过null来保证自动close()但不是线程安全的
- *
- */
- classIteratorImplimplementsBDBIterator{
- KcurrentKey=null;
- VcurrentValue=null;
- DatabaseEntrykeyEntry=null;
- DatabaseEntryvalueEntry=null;
- publicIteratorImpl(){
- if(cursor!=null){
- cursor.close();
- cursor=null;
- }
- cursor=db.openCursor(null,null);//这里不配值CursorConfig了
- }
- @Override
- publicvoidclose(){
- cursor.close();
- cursor=null;
- }
- @Override
- publicObjectcurrentKey(){
- returncurrentKey;
- }
- @Override
- publicObjectcurrentValue(){
- returncurrentValue;
- }
- @Override
- publicbooleanhasNext(){
- keyEntry=newDatabaseEntry();
- valueEntry=newDatabaseEntry();
- cursor.getNext(keyEntry,valueEntry,LockMode.DEFAULT);
- returnhas();
- }
- @Override
- publicbooleanhasPrev(){
- keyEntry=newDatabaseEntry();
- valueEntry=newDatabaseEntry();
- cursor.getPrev(keyEntry,valueEntry,LockMode.DEFAULT);
- returnhas();
- }
- publicbooleanhas(){
- if(keyEntry.getData()==null)
- returnfalse;
- try{
- currentKey=(K)newString(keyEntry.getData(),"gb2312");
- currentValue=(V)valueBinding.entryToObject(valueEntry);
- if(currentValue!=null)
- returntrue;
- }catch(UnsupportedEncodingExceptione){
- e.printStackTrace();
- }
- returnfalse;
- }
- }
- publicstaticvoidmain(String[]args){
- BDBUtil<Integer,Student>bDB=newBDBUtil<Integer,Student>("testDB",Student.class);
- Students1=newStudent(1,"ylf");
- Students2=newStudent(2,"dsb");
- Students3=newStudent(3,"dbc");
- bDB.put(1,s1);
- bDB.put(2,s2);
- bDB.put(3,s3);
- BDBIteratorit=bDB.getIterator();
- Students=null;
- intno=0;
- while(it.hasNext()){
- s=(Student)it.currentValue();
- no=Integer.parseInt((String)it.currentKey());
- System.out.println("mynameis"+s.getName()+"nois"+s.getNo()+""+no);
- }
- while(it.hasPrev()){
- s=(Student)it.currentValue();
- no=Integer.parseInt((String)it.currentKey());
- System.out.println("mynameis"+s.getName()+"nois"+s.getNo()+""+no);
- }
- it.close();
- BDBIteratorit2=bDB.getIterator();
- while(it2.hasNext()){
- s=(Student)it2.currentValue();
- no=Integer.parseInt((String)it2.currentKey());
- System.out.println("mynameis"+s.getName()+"nois"+s.getNo()+""+no);
- }
- it2.close();
- System.out.println(bDB.size());
- s=bDB.find(2);
- System.out.println("findmynameis"+s.getName());
- bDB.close();
- }