zoukankan      html  css  js  c++  java
  • Berkely DB Java Edition学习笔记

    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.     }  
  • 相关阅读:
    洛谷 P1875 佳佳的魔法药水
    洛谷 P4822 [BJWC2012]冻结
    洛谷 P6175 无向图的最小环问题
    洛谷 P1312 Mayan游戏
    洛谷 P1311 选择客栈
    洛谷 T150024 矩形面积并(扫描线)
    洛谷 P1311 选择客栈
    洛谷 P1514 引水入城
    洛谷 P1310 表达式的值
    求和(团队题目)
  • 原文地址:https://www.cnblogs.com/zheh/p/3910346.html
Copyright © 2011-2022 走看看