BerkelyDB学习笔记

来源:互联网 发布:最近上映的网络电视剧 编辑:程序博客网 时间:2024/04/19 11:39
Berkely DB对于高并发、要求速度快的应用来说是个不错的选择,mysql就是用BDB实现的(mysql的后台) ,mysql快,BDB比mysql还要快N倍。BDB是一种嵌入式的、非关系数据库,它与其他的关系数据库RMDBS不同,它没有提供SQL,而是提供了自己的访问接口。作为一种嵌入式的数据库,它是进程内模式的,也就是说它和应用程序在同一内存空间运行,所以速度要高很多,与嵌入式的数据库如Derby、HSQLDB(都是RMDBS的)相比,它效率更高,使用方法也有很大的不同。现在BDB以被Oracle收购。Berkely DB提供的文档Getting Started with Berkeley DB Java Edition可以说是短小精悍(113页),入门相当不错。下面Get Start吧: 
Environment: 
首先要接触的就是Environment了,使用它来open database以及做一管理方面的事情. 
创建Environment,还需要Environment的一些配置信息EnvironmentConfig。 
下面是创建的过程: 
Java代码  收藏代码
  1. EnvironmentConfig envConfig = new EnvironmentConfig();  
  2. envConfig.setAllowCreate(true);  
  3. myDbEnvironment = new Environment(new File("/export/dbEnv"),  
  4. envConfig);  

其中EnvironmentConfig提供了许多配置参数,常用的有: 
envConfig.setAllowCreate()//如果不存在的env的话,是否要创建一个新的 
envConfig.setReadOnly()//是否为只读的 
envConfig.setTransactional()//是否使用事务 
参数都是boolean类型的 
除了EnvironmentConfig外,还有EnvironmentMutableConfig,他实际是EnvironmentConfig的父类,使用他来配置在创建完Environment之后可以改变 
的属性: 
setCachePercent()//设置cache的大小占JVM memory的百分比 
setCacheSize()//设置cache的大小 
setTxnNoSync()//事务提交是否将改变的记录写入磁盘 
setTxnWriteNoSync()//事务提交是否将log写入磁盘 
下面看一下使用EnvironmentMutableConfig的方法: 
Java代码  收藏代码
  1. Environment myEnv = new Environment(new File("/export/dbEnv"), null);  
  2. EnvironmentMutableConfig envMutableConfig =  
  3. new EnvironmentMutableConfig();  
  4. envMutableConfig.setTxnNoSync(true);  
  5. myEnv.setMutableConfig(envMutableConfig);  

Environment通过close来关闭,释放资源 
下面看看Environment在管理方面的一些方法: 
可以通过Environment获得EnvironmentStats,他提供了Environment一些状态信息, 
例如使用 
Java代码  收藏代码
  1. long cacheMisses = myEnv.getStats(null).getNCacheMiss();  

我们可以获得cache未命中的次数,据此来调整cache的大小 
可以同过Environment.getDatabaseNames()来获得Environment的数据库的名字: 
Java代码  收藏代码
  1. List myDbNames = myDbEnv.getDatabaseNames();  
  2. for(int i=0; i < myDbNames.size(); i++) {  
  3. System.out.println("Database Name: " + (String)myDbNames.get(i));  
  4. }  

可以通过Environment.removeDatabase()来删除一个数据库: 
Java代码  收藏代码
  1. String dbName = myDB.getDatabaseName();  
  2. myDB.close();  
  3. myDBEnv.removeDatabase(null,dbName);  

可以使用Environment.renameDatabase()来重新命名一个数据库: 
Java代码  收藏代码
  1. String dbName = myDB.getDatabaseName();  
  2. String dbNewName = new String(dbName + ".new""UTF-8");  
  3. myDB.close();  
  4. myDBEnv.renameDatabase(null,dbName,dbNewName);  

可以使用Environment.truncateDatabase()来删除数据库中的所有记录: 
Java代码  收藏代码
  1. myEnv.truncate(null// txn handle  
  2. myDatabase.getDatabaseName(), // database name  
  3. true//whether to return the count of deleted records  
  4. );  

第三个参数是否返回删除的记录数,性能有很大不同。false的话会很快 
Database: 
最重要的一些操作大多都在Database里了,和Environment一样,它也有许多 
配置的选项DatabaseConfig,我们先看看选项: 
DatabaseConfig.setAllowCreate()//不能存在的话是open操作否创建新的 
DatabaseConfig.setBtreeComparator()//设置Btree的比较器 
DatabaseConfig.setDuplicateComparator()//设置判断重复的比较器 
DatabaseConfig.setSortedDuplicates()//是否允许重复的记录 
DatabaseConfig.setExclusiveCreate()//设为true,如果当前数据库已存在,则open失败,也就是说open操作会导致一个新的数据库被创建,默认为false 
DatabaseConfig.setReadOnly()//是否是只读的 
DatabaseConfig.setTransactional()//是否使用事务 
下面我们看看Database的使用流程: 
Java代码  收藏代码
  1. EnvironmentConfig envConfig = new EnvironmentConfig();  
  2. envConfig.setAllowCreate(true);  
  3. myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);  
  4. DatabaseConfig dbConfig = new DatabaseConfig();  
  5. dbConfig.setAllowCreate(true);  
  6. myDatabase = myDbEnvironment.openDatabase(null,  
  7. "sampleDatabase",  
  8. dbConfig);  

我们通过Environment的openDatabase来创建Database对象。使用完了Database使用 
close方法来关闭数据库释放资源。 
Database Records 
Database Record是保存在数据库的内容,包含Key和value两部分,他们都被封装成 
DatabaseEntry,DatabaseEntry只能存放字节数组,所以只要能把Key和Value是什么 
类型的,只要能转化成字节数组就可以被DatabaseEntry封装。基本类型JE都有对应的Binding,复杂的类型可以使用序列化和自定义binding来实现。 
下那面我们看看一个使用方法: 
Java代码  收藏代码
  1. String aKey = "key";  
  2. String aData = "data";  
  3. try {  
  4. DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));  
  5. DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));  
  6. catch (Exception e) {  
  7. }  

我们不应该依赖机器默认的编码,通常要指定特定的编码方法getBytes("UTF-8"); 
我们先看看怎么从数据库中读写记录: 
通过Database.put()和Database.get()我们可以从数据库中读写记录 
put: 
Java代码  收藏代码
  1. String aKey = "myFirstKey";  
  2. String aData = "myFirstData";  
  3. try {  
  4. DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));  
  5. DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));  
  6. myDatabase.put(null, theKey, theData);  
  7. catch (Exception e) {  
  8. }  

get: 
Java代码  收藏代码
  1. String aKey = "myFirstKey";  
  2. try {  
  3. DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));  
  4. DatabaseEntry theData = new DatabaseEntry();  
  5.   
  6. if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) ==  
  7. OperationStatus.SUCCESS) {  
  8.   
  9. byte[] retData = theData.getData();  
  10. String foundData = new String(retData, "UTF-8");  
  11. System.out.println("For key: '" + aKey + "' found data: '" +  
  12. foundData + "'.");  
  13. else {  
  14.   System.out.println("No record found for key '" + aKey + "'.");  
  15. }  
  16. catch (Exception e) {  
  17. }  

删除操作: 
Java代码  收藏代码
  1. String aKey = "myFirstKey";  
  2. DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));  
  3. myDatabase.delete(null, theKey);  

使用BIND APIs来操作基本类型: 
我们可以使用JE提供的Bind Apis来操作数字类型和字符串类型: 
以Long为例: 
存储数据使用Bind Apis一般步骤如下: 
1、通过EntryBinding binding =TupleBinding.getPrimitiveBinding(Long.class); 
2、通过EntryBinding 把数据放到DatabaseEntry中: 
myBinding.objectToEntry(data, dataEntry); 
获取数据使用Bind Apis一般步骤如下: 
1、通过EntryBinding binding =TupleBinding.getPrimitiveBinding(Long.class); 
2、通过EntryBinding将Entry转换成Object Long theLong = (Long) myBinding.entryToObject(theData); 
下面代码以测试的形式演示了整个过程: 
Java代码  收藏代码
  1. package edu.jlu.fuliang;  
  2.   
  3. import java.io.File;  
  4.   
  5. import com.sleepycat.bind.EntryBinding;  
  6. import com.sleepycat.bind.tuple.TupleBinding;  
  7. import com.sleepycat.je.Database;  
  8. import com.sleepycat.je.DatabaseConfig;  
  9. import com.sleepycat.je.DatabaseEntry;  
  10. import com.sleepycat.je.Environment;  
  11. import com.sleepycat.je.EnvironmentConfig;  
  12. import com.sleepycat.je.LockMode;  
  13.   
  14. import junit.framework.TestCase;  
  15.   
  16. public class PrimitiveBindingTest extends TestCase{  
  17.     private Environment env;  
  18.     private Database db;  
  19.     private String key = "akey";  
  20.     private Long data = 1234556633L;  
  21.       
  22.     public void setUp()throws Exception{  
  23.         EnvironmentConfig envConfig = new EnvironmentConfig();  
  24.         envConfig.setAllowCreate(true);  
  25.         env = new Environment(new File("etc/dbEnv"),envConfig);  
  26.         DatabaseConfig dbConfig = new DatabaseConfig();  
  27.         dbConfig.setAllowCreate(true);  
  28.         db = env.openDatabase(null"myDB", dbConfig);  
  29.         DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("UTF-8"));  
  30.         DatabaseEntry dataEntry = new DatabaseEntry();  
  31.           
  32.         EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);  
  33.         myBinding.objectToEntry(data, dataEntry);  
  34.         db.put(null, keyEntry, dataEntry);  
  35.     }  
  36.       
  37.     public void testGet()throws Exception{  
  38.         DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("UTF-8"));  
  39.         DatabaseEntry dataEntry = new DatabaseEntry();  
  40.         EntryBinding binding = TupleBinding.getPrimitiveBinding(Long.class);  
  41.         db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);  
  42.         Long l = (Long)binding.entryToObject(dataEntry);  
  43.         assertEquals(l,data);  
  44.     }  
  45.     public void tearDown()throws Exception{  
  46.         db.close();  
  47.         env.truncateDatabase(null"myDB",false);  
  48.         env.close();  
  49.     }  
  50.       
  51. }  

序列化复杂的类型 
步骤如下: 
1、要存储的对象的类需要实现java.io.Serializable 
2、打开两个数据库,一个存放数据,另一个存放类的信息 
3、实例化com.sleepycat.bind.serial.StoredClassCatalog对象 
4、创建uses com.sleepycat.bind.serial.SerialBinding对象 
5、使用SerialBinding把对象放到DatabaseEntry中 
下面是使用一个能够完整描述这个过程的例子来说明这个过程: 
Java代码  收藏代码
  1. package edu.jlu.fuliang;  
  2.   
  3. import java.io.File;  
  4.   
  5. import com.sleepycat.bind.EntryBinding;  
  6. import com.sleepycat.bind.serial.SerialBinding;  
  7. import com.sleepycat.bind.serial.StoredClassCatalog;  
  8. import com.sleepycat.je.Database;  
  9. import com.sleepycat.je.DatabaseConfig;  
  10. import com.sleepycat.je.DatabaseEntry;  
  11. import com.sleepycat.je.DatabaseException;  
  12. import com.sleepycat.je.Environment;  
  13. import com.sleepycat.je.EnvironmentConfig;  
  14. import com.sleepycat.je.LockMode;  
  15.   
  16. import junit.framework.TestCase;  
  17.   
  18. public class SerializableTypeTest extends TestCase{  
  19.     private Person person;  
  20.     private Environment env;  
  21.     private Database db,classDB;  
  22.     private StoredClassCatalog classCatalog;  
  23.       
  24.     public void setUp()throws Exception{  
  25.         person = new Person();  
  26.         person.setAge(12);  
  27.         person.setName("zhansan");  
  28.         person.setSex('m');  
  29.           
  30.         EnvironmentConfig envConfig = new EnvironmentConfig();  
  31.         envConfig.setAllowCreate(true);  
  32.         env = new Environment(new File("etc/dbEnv"),envConfig);  
  33.         DatabaseConfig dbConfig = new DatabaseConfig();  
  34.         dbConfig.setAllowCreate(true);  
  35.         db = env.openDatabase(null"myDB", dbConfig);  
  36.         classDB = env.openDatabase(null"classDB", dbConfig);  
  37.         classCatalog = new StoredClassCatalog(classDB);  
  38.         EntryBinding dataBinding = new SerialBinding(classCatalog,Person.class);  
  39.               
  40.         DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));  
  41.         DatabaseEntry dataEntry = new DatabaseEntry();  
  42.         dataBinding.objectToEntry(person, dataEntry);  
  43.         db.put(null, keyEntry, dataEntry);  
  44.     }  
  45.       
  46.     public void testGet()throws Exception{  
  47.         EntryBinding dataBinding = new SerialBinding(classCatalog,Person.class);  
  48.         
  49.         DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));  
  50.         DatabaseEntry dataEntry = new DatabaseEntry();  
  51.         db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);  
  52.         Person p = (Person)dataBinding.entryToObject(dataEntry);  
  53.         assertEquals(p.getName(),person.getName());  
  54.         assertEquals(p.getAge(),person.getAge());  
  55.         assertEquals(p.getSex(), person.getSex());  
  56.     }  
  57.       
  58.     public void tearDown()throws Exception{  
  59.         db.close();  
  60.         classDB.close();  
  61.         env.truncateDatabase(null"myDB"false);  
  62.         env.truncateDatabase(null"classDB"false);  
  63.         env.close();  
  64.     }  
  65. }  

要存储的对象对应的类 
Java代码  收藏代码
  1. package edu.jlu.fuliang;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class Person implements Serializable{  
  6.     private String name;  
  7.     private int age;  
  8.     private char sex;  
  9.   
  10.     public int getAge() {  
  11.         return age;  
  12.     }  
  13.   
  14.     public void setAge(int age) {  
  15.         this.age = age;  
  16.     }  
  17.   
  18.     public String getName() {  
  19.         return name;  
  20.     }  
  21.   
  22.     public void setName(String name) {  
  23.         this.name = name;  
  24.     }  
  25.   
  26.     public char getSex() {  
  27.         return sex;  
  28.     }  
  29.   
  30.     public void setSex(char sex) {  
  31.         this.sex = sex;  
  32.     }  
  33. }  

自定义元组绑定: 
存储复杂对象自定义元组绑定的步骤: 
1、创建要存储的对象,这个对象的类没有必要实现Serializable接口: 
2、扩展com.sleepycat.bind.tuple.TupleBinding来实现自定义的Binging 
3、创建2步欻关键的自定义binding对象 
4、将创建的对象是用自定义个binding放到DatabaseEntry中 
5、使用put方法存入数据库 
下面的例子说明了这个过程: 
自定义Binging: 
Java代码  收藏代码
  1. package edu.jlu.fuliang;  
  2.   
  3. import com.sleepycat.bind.tuple.TupleBinding;  
  4. import com.sleepycat.bind.tuple.TupleInput;  
  5. import com.sleepycat.bind.tuple.TupleOutput;  
  6.   
  7. public class PersonTupleBinding extends TupleBinding{  
  8.   
  9.     @Override  
  10.     public Object entryToObject(TupleInput ti) {  
  11.         Person person = new Person();  
  12.         person.setName(ti.readString());  
  13.         person.setAge(ti.readInt());  
  14.         person.setSex(ti.readChar());  
  15.         return person;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void objectToEntry(Object obj, TupleOutput output) {  
  20.         Person person = (Person)obj;  
  21.         output.writeString(person.getName());  
  22.         output.writeInt(person.getAge());  
  23.         output.writeChar(person.getSex());  
  24.     }  
  25. }  

put/get的使用过程: 
Java代码  收藏代码
  1. package edu.jlu.fuliang;  
  2.   
  3. import java.io.File;  
  4. import com.sleepycat.je.Database;  
  5. import com.sleepycat.je.DatabaseConfig;  
  6. import com.sleepycat.je.DatabaseEntry;  
  7. import com.sleepycat.je.DatabaseException;  
  8. import com.sleepycat.je.Environment;  
  9. import com.sleepycat.je.EnvironmentConfig;  
  10. import com.sleepycat.je.LockMode;  
  11.   
  12. import junit.framework.TestCase;  
  13.   
  14. public class CustomTupleBindingTest extends TestCase{  
  15.     private Person person;  
  16.     private Environment env;  
  17.     private Database db;  
  18.       
  19.     public void setUp()throws Exception{  
  20.         person = new Person();  
  21.         person.setAge(12);  
  22.         person.setName("zhansan");  
  23.         person.setSex('m');  
  24.           
  25.           
  26.         EnvironmentConfig envConfig = new EnvironmentConfig();  
  27.         envConfig.setAllowCreate(true);  
  28.         env = new Environment(new File("etc/dbEnv"),envConfig);  
  29.         DatabaseConfig dbConfig = new DatabaseConfig();  
  30.         dbConfig.setAllowCreate(true);  
  31.         db = env.openDatabase(null"myDB", dbConfig);  
  32.         PersonTupleBinding binding = new PersonTupleBinding();  
  33.         DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));  
  34.         DatabaseEntry dataEntry = new DatabaseEntry();  
  35.         binding.objectToEntry(person, dataEntry);  
  36.         db.put(null, keyEntry, dataEntry);  
  37.           
  38.     }  
  39.       
  40.     public void testGet()throws Exception{  
  41.         PersonTupleBinding binding = new PersonTupleBinding();  
  42.           
  43.         DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));  
  44.         DatabaseEntry dataEntry = new DatabaseEntry();  
  45.         db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);  
  46.         Person p = (Person)binding.entryToObject(dataEntry);  
  47.         assertEquals(p.getName(),person.getName());  
  48.         assertEquals(p.getAge(),person.getAge());  
  49.         assertEquals(p.getSex(), person.getSex());  
  50.     }  
  51.     public void tearDown()throws Exception{  
  52.         db.close();  
  53.         env.truncateDatabase(null"myDB"false);  
  54.         env.close();  
  55.     }  
  56. }  
2 0
原创粉丝点击