• Berkeley DB Java Edition使用说明


    在使用Berkeley DB c++ Edition的时候发现有些接口不是太了解,发现网上好多都是Java版本的信息,对付发现他们的命名基本相同。所以转载一下以便以后查找。

    一、 简介 
    Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。 
    l 能够高效率的处理1到1百万条记录,制约JE数据库的往往是硬件系统,而不是JE本身。 
    l 多线程支持,JE使用超时的方式来处理线程间的死琐问题。 
    l Database都采用简单的key/value对应的形式。 
    l 事务支持。 
    l 允许创建二级库。这样我们就可以方便的使用一级key,二级key来访问我们的数据。 
    l 支持RAM缓冲,这样就能减少频繁的IO操作。 
    l 支持日志。 
    l 数据备份和恢复。 
    l 游标支持。 
    二、 获取JE 
    JE下载地址: 
    http://www.oracle.com/technology/software/products/berkeley-db/je/index.html 
    解开包后 把JE_HOME/lib/je-<version>.jar 中的jar文件添加到你的环境变量中就可以使用je了。 
    相关帮助文档可以参考 JE_HOME/docs/index.html 
    源代码见JE_HOME/src/*.* 
    三、 JE常见的异常 
    DatabaseNotFoundException 当没有找到指定的数据库的时候会返回这个异常 
    DeadlockException 线程间死锁异常 
    RunRecoveryException 回收异常,当发生此异常的时候,你必须得重新打开环境变量。 
    四、 关于日志文件必须了解的六项 
    JE的日志文件跟其他的数据库的日志文件不太一样,跟C版的DBD也是有区别的 
    l JE的日志文件只能APPEND,第一个日志文件名是 00000000.jdb,当他增长到一定大小的时候(默认是10M),开始写第二个日志文件00000001.jdb,已此类推。 
    l 跟C版本有所不同,JE的数据日志和事务日志是放在一起的,而不是分开放的。 
    l JE cleaner负责清扫没用到的磁盘空间,删除后,或者更新后新的记录会追加进来,而原有的记录空间就不在使用了,cleaner负责清理不用的空间。 
    l 清理并不是立即进行的,当你关闭你的数据库环境后,通过调用一个cleaner方法来清理。 
    l 清理也不是只动执行的,需要你自己手动调用cleaner 方法来定时清理的。 
    l 日志文件的删除仅发生在检查点之后。cleaner准备出哪些log 文件需要被删除,当检查点过后,删掉一些不在被使用的文件。每写20M的日志文件就执行一次检查点,默认下。 
    五、 创建数据库环境 
    JE要求在任何DATABASE操作前,要先打开数据库环境,就像我们要使用数据库的话必须得先建立连接一样。你可以通过数据库环境来创建和打开database,或者更改database名称和删除database. 
    可以通过Environments对象来打开环境,打开环境的时候设置的目录必须是已经存在的目录,否则会出错误。默认情况下,如果指定的database不存在则不会自动创建一个新的detabase,但可以通过设置setAllowCreate来改变这一情况。 
    1. 打开database环境 
    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package je.gettingStarted;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
    import com.sleepycat.je.EnvironmentConfig;
    import java.io.File;
     
    ...
     
    Environment myDbEnvironment = null;
     
    try {
        EnvironmentConfig envConfig = new EnvironmentConfig();
        envConfig.setAllowCreate(true);//如果不存在则创建一个
        myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
    } catch (DatabaseException dbe) {
        // 错误处理
    }


    2. 关闭database环境 
    可以通过Environment.close()这个方法来关闭database环境,当你完成数据库操作后一定要关闭数据库环境。 
    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
     
    ...
     
    try {
        if (myDbEnvironment != null) {
            myDbEnvironment.close();
        } 
    } catch (DatabaseException dbe) {
        // Exception handling goes here
    }


    3. 清理日志 
    通常在关闭数据库连接的时候,有必要清理下日志,用以释放更多的磁盘空间。我们可以在Environment.close前执行下Environment.cleanLog()来达到此目的。 
    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
     
    ...
     
    try {
        if (myDbEnvironment != null) {
            myDbEnvironment.cleanLog(); // 在关闭环境前清理下日志
            myDbEnvironment.close();
        } 
    } catch (DatabaseException dbe) {
        // Exception handling goes here
    }


    4. Database环境的配置 
    可以通过EnvironmentConfig这个对象来配置database环境。如果想得到当前环境的配置信息则可以通过Environment.getConfig()方法得到当前环境的配置信息。 
    也可以使用EnvironmentMutableConfig来配置环境,其实 EnvironmentConfig是EnvironmentMutableConfig的子类,所以EnvironmentMutableConfig能够使用的设置,EnvironmentConfig也同样能够使用。 
    如果你要获取当前环境的使用情况,那么你可以通过使用EnvironmentStats.getNCacheMiss().来监视RAM cache命中率。EnvironmentStats可以由Environment.getStats()方法获取。 
    EnvironmentConfig常见方法介绍 
    l EnvironmentConfig.setAllowCreate() ; 
    如果设置了true则表示当数据库环境不存在时候重新创建一个数据库环境,默认为false. 
    l EnvironmentConfig.setReadOnly() 
    以只读方式打开,默认为false. 
    l EnvironmentConfig.setTransactional() 
    事务支持,如果为true,则表示当前环境支持事务处理,默认为false,不支持事务处理。 
    EnvironmentMutableConfig的介绍 
    l setCachePercent() 
    设置当前环境能够使用的RAM占整个JVM内存的百分比。 
    l setCacheSize() 
    设置当前环境能够使用的最大RAM。单位BYTE 
    l setTxnNoSync() 
    当提交事务的时候是否把缓存中的内容同步到磁盘中去。 
    true 表示不同步,也就是说不写磁盘 
    l setTxnWriteNoSync() 
    当提交事务的时候,是否把缓冲的log写到磁盘上 
    true 表示不同步,也就是说不写磁盘 
    示例一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package je.gettingStarted;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
    import com.sleepycat.je.EnvironmentConfig;
    import java.io.File;
     
    ...
     
    Environment myDatabaseEnvironment = null;
    try {
        EnvironmentConfig envConfig = new EnvironmentConfig();
        //当环境不存在的时候自动创建环境
           envConfig.setAllowCreate(true);
           //设置支持事务
           envConfig.setTransactional(true);
        myDatabaseEnvironment = 
            new Environment(new File("/export/dbEnv"), envConfig);
    } catch (DatabaseException dbe) {
       System.err.println(dbe.toString());
       System.exit(1);
    }


    示例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package je.gettingStarted;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
    import com.sleepycat.je.EnvironmentMutableConfig;
    import java.io.File;
    ...
    try {
        Environment myEnv = new Environment(new File("/export/dbEnv"), null);
        EnvironmentMutableConfig envMutableConfig = 
            new EnvironmentMutableConfig();
        envMutableConfig.setTxnNoSync(true);
        myEnv.setMutableConfig(envMutableConfig); 
    } catch (DatabaseException dbe) {
        // Exception handling goes here
    }


    示例三:

    1
    2
    3
    4
    5
    import com.sleepycat.je.Environment;
    ...
    //没有命中的CACHE
    long cacheMisses = myEnv.getStats(null).getNCacheMiss();
    ...


    5. Database操作 
    在BDB中,数据是以key/value方式成队出现的。 
    打开database 
    可以通过environment.openDatabase()方法打开一个database,在调用这个方法的时候必须指定database的名称。和databaseConfig() (注:数据库设置) 
    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package je.gettingStarted;
    import com.sleepycat.je.Database;
    import com.sleepycat.je.DatabaseConfig;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Environment;
    import com.sleepycat.je.EnvironmentConfig;
    import java.io.File;
    ...
    Environment myDbEnvironment = null;
    Database myDatabase = null;
    ...
    try {
        // 打开一个环境,如果不存在则创建一个
        EnvironmentConfig envConfig = new EnvironmentConfig();
        envConfig.setAllowCreate(true);
        myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
     
        // 打开一个数据库,如果数据库不存在则创建一个
        DatabaseConfig dbConfig = new DatabaseConfig();
        dbConfig.setAllowCreate(true);
        myDatabase = myDbEnvironment.openDatabase(null, 
    "sampleDatabase", dbConfig); //打开一个数据库,数据库名为
                                       //sampleDatabase,数据库的配置为dbConfig
    } catch (DatabaseException dbe) {
        // 错误处理
    }


    关闭database 
    通过调用Database.close()方法来关闭数据库,但要注意,在关闭数据库前必须得先把游标先关闭。 
    使用示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Database;
    import com.sleepycat.je.Environment;
    ...
    try {
            if (myDatabase != null) {
                myDatabase.close();
            }
            if (myDbEnvironment != null) {
                myDbEnvironment.close();
            }
    } catch (DatabaseException dbe) {
        // 错误处理
    }


    设置数据库属性 
    其实设置数据库属性跟设置环境属性差不多,JE中通过DatabaseConfig对象来设置数据库属性。你能够设置的数据库属性如下。 
    l DatabaseConfig.setAllowCreate() 
    如果是true的话,则当不存在此数据库的时候创建一个。 
    l DatabaseConfig.setBtreeComparator() 
    设置用于Btree比较的比较器,通常是用来排序 
    l DatabaseConfig.setDuplicateComparator() 
    设置用来比较一个key有两个不同值的时候的大小比较器。 
    l DatabaseConfig.setSortedDuplicates() 
    设置一个key是否允许存储多个值,true代表允许,默认false. 
    l DatabaseConfig.setExclusiveCreate() 
    以独占的方式打开,也就是说同一个时间只能有一实例打开这个database。 
    l DatabaseConfig.setReadOnly() 
    以只读方式打开database,默认是false. 
    l DatabaseConfig.setTransactional() 
    如果设置为true,则支持事务处理,默认是false,不支持事务。 
    使用示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package je.gettingStarted;
    import com.sleepycat.je.DatabaseException;
    import com.sleepycat.je.Database;
    import com.sleepycat.je.DatabaseConfig;
    ...
    // Environment open omitted for brevity
    ...
    Database myDatabase = null;
    try {
        DatabaseConfig dbConfig = new DatabaseConfig();
        dbConfig.setAllowCreate(true);
        dbConfig.setSortedDuplicates(true);
        myDatabase = 
            myDbEnv.openDatabase(null, 
                                 "sampleDatabase", 
                                 dbConfig); 
    } catch (DatabaseException dbe) {
        // Exception handling goes here.
    }


    一些用来管理的方法 
    l Database.getDatabaseName() 
    取得数据库的名称 
    如:String dbName = myDatabase.getDatabaseName(); 
    l Database.getEnvironment() 
    取得包含这个database的环境信息 
    如:Environment theEnv = myDatabase.getEnvironment(); 
    l Database.preload() 
    预先加载指定bytes的数据到RAM中。 
    如:myDatabase.preload(1048576l); // 1024*1024 
    l Environment.getDatabaseNames() 
    返回当前环境下的数据库列表 
    如:

    1
    2
    3
    4
    5
    import java.util.List;
    List myDbNames = myDbEnv.getDatabaseNames();
    for(int i=0; i < myDbNames.size(); i++) {
        System.out.println("Database Name: " + (String)myDbNames.get(i));
    }


    l Environment.removeDatabase() 
    删除当前环境中指定的数据库。 
    如:

    1
    2
    3
    String dbName = myDatabase.getDatabaseName();
    myDatabase.close();
    myDbEnv.removeDatabase(null, dbName);


    l Environment.renameDatabase() 
    给当前环境下的数据库改名 
    如:

    1
    2
    3
    4
    String oldName = myDatabase.getDatabaseName();   
    String newName = new String(oldName + ".new", "UTF-8");
    myDatabase.close();
    myDbEnv.renameDatabase(null, oldName, newName);


    l Environment.truncateDatabase() 
    清空database内的所有数据,返回清空了多少条记录。 
    如:

    1
    2
    3
    Int numDiscarded= myEnv.truncate(null,
    myDatabase.getDatabaseName(),true); 
    System.out.println("一共删除了 " + numDiscarded +" 条记录 从数据库 " + myDatabase.getDatabaseName());


    6. Database 记录 
    JE的记录包含两部分,key键值和value数据值,这两个值都是通过DatabaseEntry对象封装起来,所以说如果要使用记录,则你必须创建两个DatabaseEntry对象,一个是用来做为key,另外一个是做为value. 

    DatabaseEntry能够支持任何的能够转换为bytes数组形式的基本数据。包括所有的JAVA基本类型和可序列化的对象. 

    使用记录 
    示例一:把字符串转换DatabaseEntry

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package je.gettingStarted;
    import com.sleepycat.je.DatabaseEntry;
    ...
    String aKey = "key"; 
    String aData = "data";
    try {
     //设置key/value,注意DatabaseEntry内使用的是bytes数组
     DatabaseEntry theKey=new DatabaseEntry(aKey.getBytes("UTF-8"));
     DatabaseEntry theData=new DatabaseEntry(aData.getBytes("UTF-8"));
    } catch (Exception e) {
        // 错误处理
    }


    示例二:把DatabaseEntry里的数据转换成字符串

    1
    2
    3
    4
    byte[] myKey = theKey.getData();
    byte[] myData = theData.getData();
    String key = new String(myKey, "UTF-8");
    String data = new String(myData, "UTF-8");


    读和写database 记录 
    读和写database记录的时候大体是基本一样的,唯一有区别的是每个key写是否允许写多条记录,默认情况下是不支持多条记录的。 
    a) 你可以使用如下方法向database 里添加记录 
    l Database.put() 
    向database中添加一条记录。如果你的database不支持一个key对应多个data或当前database中已经存在该key了,则使用此方法将使用新的值覆盖旧的值。 
    l Database.putNoOverwrite() 
    向database中添加新值但如果原先已经有了该key,则不覆盖。不管database是否允许支持多重记录(一个key对应多个value),只要存在该key就不允许添加,并且返回perationStatus.KEYEXIST信息。 
    l Database.putNoDupData() 
    想database中添加一条记录,如果database中已经存在了相同的 key和value则返回 OperationStatus.KEYEXIST. 
    使用示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package je.gettingStarted;
        import com.sleepycat.je.Database;
        import com.sleepycat.je.DatabaseEntry;
        ...
        String aKey = "myFirstKey";
        String aData = "myFirstData";
        try {
            DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
            DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
            myDatabase.put(null, theKey, theData);
        } catch (Exception e) {
            // Exception handling goes here
        }


    b) 你可以使用如下方法从database 里读取记录 
    1. Database.get() 
    基本的读记录的方法,通过key的方式来匹配,如果没有改记录则返回OperationStatus.NOTFOUND。 
    l Database.getSearchBoth() 
    通过key和value来同时匹配,同样如果没有记录匹配key和value则会返回OperationStatus.NOTFOUND。 
    使用示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package je.gettingStarted;
    import com.sleepycat.je.Database;
    import com.sleepycat.je.DatabaseEntry;
    import com.sleepycat.je.LockMode;
    import com.sleepycat.je.OperationStatus;
    ...
    String aKey = "myFirstKey";
     
    try {
        DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
        DatabaseEntry theData = new DatabaseEntry();
        
        if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) ==
            OperationStatus.SUCCESS) {
            byte[] retData = theData.getData();
            String foundData = new String(retData, "UTF-8");
            System.out.println("For key: '" + aKey + "' found data: '" + 
                                foundData + "'.");
        } else {
            System.out.println("No record found for key '" + aKey + "'.");
        } 
    } catch (Exception e) {
        // Exception handling goes here
    }


    c) 删除记录 
    可以使用Database.delete()这个方法来删除记录。如果你的database支持多重记录,则当前key下的所有记录都会被删除,如果只想删除多重记录中的一条则可以使用游标来删除。 
    当然你也可以使用Environment.truncateDatabase()这个方法来清空database 中的所有记录。 

    使用示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package je.gettingStarted;
    import com.sleepycat.je.Database;
    import com.sleepycat.je.DatabaseEntry;
    ...
    try {
        String aKey = "myFirstKey";
        DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
        myDatabase.delete(null, theKey); 
    } catch (Exception e) {
    }


    d) 提交事务 
    当你对database进行了写操作的时候,你的修改不一定马上就能生效,有的时候他仅仅是缓存在RAM中,如果想让你的修改立即生效,则可以使用Environment.sync()方法来把数据同步到磁盘中去。 
    e) 不同类型的数据的处理 
    1. 你可以使用DatabaseEntry来绑定基本的JAVA数据类型,主要有String、Character、Boolean、Byte、Short、Integer、Long、Float、Double. 
    使用示例一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package je.gettingStarted;
                  import com.sleepycat.bind.EntryBinding;
                  import com.sleepycat.bind.tuple.TupleBinding;
                  import com.sleepycat.je.DatabaseEntry;
                  ...
                  try {
                      String aKey = "myLong";
                      DatabaseEntry theKey = new
                      DatabaseEntry(aKey.getBytes("UTF-8"));    
     
                      Long myLong = new Long(123456789l);
                      DatabaseEntry theData = new DatabaseEntry();
                      EntryBinding myBinding =        
                      TupleBinding.getPrimitiveBinding(Long.class);
                      myBinding.objectToEntry(myLong, theData);
                      myDatabase.put(null, theKey, theData);
                  } catch (Exception e) {
                      // Exception handling goes here
                  }


    使用示例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package je.gettingStarted;
           import com.sleepycat.bind.EntryBinding;
           import com.sleepycat.bind.tuple.TupleBinding;
           import com.sleepycat.je.Database;
           import com.sleepycat.je.DatabaseEntry;
           import com.sleepycat.je.LockMode;
           import com.sleepycat.je.OperationStatus;
           ...
           Database myDatabase = null;
           try {
               String aKey = "myLong";
               DatabaseEntry theKey = new 
                  DatabaseEntry(aKey.getBytes("UTF-8"));
               DatabaseEntry theData = new DatabaseEntry();
               EntryBinding myBinding =        
                  TupleBinding.getPrimitiveBinding(Long.class);
               OperationStatus retVal = myDatabase.get(null, theKey, theData, 
                  LockMode.DEFAULT);
               String retKey = null;
               if (retVal == OperationStatus.SUCCESS) {
            Long theLong = (Long) myBinding.entryToObject(theData);
                   retKey = new String(theKey.getData(), "UTF-8");
                   System.out.println("For key: '" + retKey + "' found Long: '" + 
                                theLong + "'.");
               } else {
                   System.out.println("No record found for key '" + retKey + "'.");
               }
           } catch (Exception e) {
               // Exception handling goes here
           }

    原文地址:   http://hi.baidu.com/miningking/blog/item/8b2ffa35771b7bbfd1a2d36a.html

    另外资料来源: http://fesir.itpub.net/post/4728/253789

            http://www.iteye.com/topic/227040

  • 相关阅读:
    JSP错题纠错
    org.hibernate.NonUniqueObjectException: a different object with the same identifier value was alread---------程序报错
    SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
    Spring Mvc 的自定义拦截器
    管理系统-------------SSH框架书写登录和显示用户
    初识的Spring Mvc-----原理
    相识不易,要懂珍惜----------Spring Mvc
    我们的相识,总是那么巧。-------eclipse中搭建maven项目
    初识Web 服务(即Web Service)
    初识Spring框架
  • 原文地址:https://www.cnblogs.com/zhongwh/p/2352967.html
Copyright © 2020-2023  润新知