`
梦回大唐
  • 浏览: 3630 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

Berkeley DB Java Edition使用说明

阅读更多

一、 简介
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
       }

 

2. 可序列化的对象的绑定

1. 首先你需要创建一个可序列化对象

2. 打开或创建你的database,你需要两个,一个用来存储你的数据,另外一个用来存储类信息。

3. 实例化catalog类,这个时候你可以使用com.sleepycat.bind.serial.StoredClassCatalog,来存储你的类信息。

4. 通过com.sleepycat.bind.serial.SerialBinding来绑定数据和类。

5. 绑定并存储数据。

示例:

l 创建一个可序列化的对象

package je.gettingStarted;

import java.io.Serializable;

public class MyData implements Serializable {

private long longData;

private double doubleData;

private String description;

MyData() {

longData = 0;

doubleData = 0.0;

description = null;

}

public void setLong(long data) {

longData = data;

}

public void setDouble(double data) {

doubleData = data;

}

public void setDescription(String data) {

description = data;

}

public long getLong() {

return longData;

}

public double getDouble() {

return doubleData;

}

public String getDescription() {

return description;

}

}

l 存储数据

package je.gettingStarted;

import com.sleepycat.bind.EntryBinding;

import com.sleepycat.bind.serial.StoredClassCatalog;

import com.sleepycat.bind.serial.SerialBinding;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseConfig;

import com.sleepycat.je.DatabaseEntry;

...

String aKey = "myData";

MyData data2Store = new MyData();

data2Store.setLong(123456789l);

data2Store.setDouble(1234.9876543);

data2Store.setDescription("A test instance of this class");

try {

DatabaseConfig myDbConfig = new DatabaseConfig();

myDbConfig.setAllowCreate(true);

myDbConfig.setSortedDuplicates(true);

Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);

myDbConfig.setSortedDuplicates(false);

//打开用来存储类信息的库

Database myClassDb = myDbEnv.openDatabase(null, "classDb", myDbConfig);

// 3)创建catalog

StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);

// 4)绑定数据和类

EntryBinding dataBinding = new SerialBinding(classCatalog,

MyData.class);

DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));

// 向DatabaseEntry里写数据

DatabaseEntry theData = new DatabaseEntry();

dataBinding.objectToEntry(data2Store, theData);

myDatabase.put(null, theKey, theData);

} catch (Exception e) {

// 错误处理

}

l 读数据

package je.gettingStarted;

import com.sleepycat.bind.EntryBinding;

import com.sleepycat.bind.serial.StoredClassCatalog;

import com.sleepycat.bind.serial.SerialBinding;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseConfig;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.LockMode;

...

// The key data.

String aKey = "myData";

try {

DatabaseConfig myDbConfig = new DatabaseConfig();

myDbConfig.setAllowCreate(false);

Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);

//用来存储类信息的库

Database myClassDb = myDbEnv.openDatabase(null, "classDb", myDbConfig);

// 实例化catalog

StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);

// 创建绑定对象

EntryBinding dataBinding = new SerialBinding(classCatalog,

MyData.class);

DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));

DatabaseEntry theData = new DatabaseEntry();

myDatabase.get(null, theKey, theData, LockMode.DEFAULT);

// Recreate the MyData object from the retrieved DatabaseEntry using

// 根据存储的类信息还原数据

MyData retrievedData=(MyData)dataBinding.entryToObject(theData);

} catch (Exception e) {

// Exception handling goes here

}

3. 自定义对象的绑定

使用tuple binding 来绑定自定义数据的步骤

①. 实例化你要存储的对象

②. 通过com.sleepycat.bind.tuple.TupleBinding class来创建一个tuple binding。

③. 创建一个database,跟序列化的对象不同,你只需要创建一个。

④. 通过继承第二步的类来创建一个entry binding 对象。

⑤. 存储和使用数据

使用示例:

l 创建要存储的对象

package je.gettingStarted;

public class MyData2 {

private long longData;

private Double doubleData;

private String description;

public MyData2() {

longData = 0;

doubleData = new Double(0.0);

description = "";

}

public void setLong(long data) {

longData = data;

}

public void setDouble(Double data) {

doubleData = data;

}

public void setString(String data) {

description = data;

}

public long getLong() {

return longData;

}

public Double getDouble() {

return doubleData;

}

public String getString() {

return description;

}

}

l 创建一个TupleBinding对象

package je.gettingStarted;

import com.sleepycat.bind.tuple.TupleBinding;

import com.sleepycat.bind.tuple.TupleInput;

import com.sleepycat.bind.tuple.TupleOutput;

public class MyTupleBinding extends TupleBinding {

// 把对象转换成TupleOutput

public void objectToEntry(Object object, TupleOutput to) {

MyData2 myData = (MyData2)object;

to.writeDouble(myData.getDouble().doubleValue());

to.writeLong(myData.getLong());

to.writeString(myData.getString());

}

//把TupleInput转换为对象

public Object entryToObject(TupleInput ti) {

Double theDouble = new Double(ti.readDouble());

long theLong = ti.readLong();

String theString = ti.readString();

MyData2 myData = new MyData2();

myData.setDouble(theDouble);

myData.setLong(theLong);

myData.setString(theString);

return myData;

}

}

l 读和写数据

package je.gettingStarted;

import com.sleepycat.bind.tuple.TupleBinding;

import com.sleepycat.je.DatabaseEntry;

...

TupleBinding keyBinding = new MyTupleBinding();

MyData2 theKeyData = new MyData2();

theKeyData.setLong(123456789l);

theKeyData.setDouble(new Double(12345.6789));

theKeyData.setString("My key data");

DatabaseEntry myDate = new DatabaseEntry();

try {

// 把theKeyData 存储到DatabaseEntry里

keyBinding.objectToEntry(theKeyData, myDate);

...

// Database 进行了一些读和写操作

...

// Retrieve the key data

theKeyData = (MyData2) keyBinding.entryToObject(myDate);

} catch (Exception e) {

// 错误处理

}

f) 使用比较器

JE是使用BTrees来组织结构的,这意味着当对database的读和写需要涉及BTrees间的节点比较。这些比较在key间是经常的发生的。如果你的database支持多重记录,那么也会存在data间的比较。

默认的情况JE的比较器是按照字节的方式来进行比较的,这通常情况下能处理大多数的情况。但有的时候确实需要自定义比较器用于特殊的通途,比如说按照key来排序。

l 创建自己的比较器

其实很简单,只要你重写Comparator class中的比较方法(compare)就可以了,通过Comparator.compare()会传递给你两个byte 数组形式的值,如果你知道结构,则可以根据你自己定义的方法来进行比较


示例:

package je.gettingStarted;

import java.util.Comparator;

public class MyDataComparator implements Comparator {

public MyDataComparator() {}

public int compare(Object d1, Object d2) {

byte[] b1 = (byte[])d1;

byte[] b2 = (byte[])d2;

String s1 = new String(b1, "UTF-8");

String s2 = new String(b2, "UTF-8");

return s1.compareTo(s2);

}

}

l 让database使用你自定义的比较器

如果你想改变database中基本的排序方式,你只能重新创建database并重新导入数据。

①. DatabaseConfig.setBtreeComparator()

用于在database里两个key的比较

②. DatabaseConfig.setOverrideBtreeComparator()

如果为true则代表让database使用 DatabaseConfig.setBtreeComparator()设置的比较器来代替默认的比较器。

③. DatabaseConfig.setDuplicateComparator()

用于database可以使用多重记录的时候的data的 比较。

④. DatabaseConfig.setOverrideDuplicateComparator()

如果为true则代表让database使用 DatabaseConfig. setDuplicateComparator()设置 的比 较器来代替默认的比较器。

使用示例:

package je.gettingStarted;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseConfig;

import com.sleepycat.je.DatabaseException;

import java.util.Comparator;

...

try {

DatabaseConfig myDbConfig = new DatabaseConfig();

myDbConfig.setAllowCreate(true);

// 设置要使用的比较器

myDbConfig.setDuplicateComparator(MyDataComparator.class);

// 使用自己定义的比较器

myDbConfig.setSortedDuplicates(true);

Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);

} catch (DatabaseException dbe) {

// Exception handling goes here

}

六、 游标的使用

游标提供了遍历你database中记录的一种机制,使用游标你可以获取,添加,和删除你的记录。如果你的database支持多重记录,则可以通过游标访问同一个key下的每一个记录。

l 打开和关闭游标

要想使用游标则你必须通过Database.openCursor()方法来打开一个游标,你可以通过CursorConfig来配置你的游标。

可以通过Cursor.close()方法来关闭游标。请注意在关闭database和环境前一定要关闭游标,否则会带来错误。

打开游标示例:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.CursorConfig;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseException;

import com.sleepycat.je.Environment;

import java.io.File;

...

Environment myDbEnvironment = null;

Database myDatabase = null;

Cursor myCursor = null;

try {

myDbEnvironment = new Environment(new File("/export/dbEnv"), null);

myDatabase = myDbEnvironment.openDatabase(null, "myDB", null);

myCursor = myDatabase.openCursor(null, null);

} catch (DatabaseException dbe) {

// Exception handling goes here ...

}

关闭游标示例:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.Environment;

...

try {

...

} catch ... {

} finally {

try {

if (myCursor != null) {

myCursor.close();

}

if (myDatabase != null) {

myDatabase.close();

}

if (myDbEnvironment != null) {

myDbEnvironment.close();

}

} catch(DatabaseException dbe) {

System.err.println("Error in close: " + dbe.toString());

}

}

l 通过游标来获取记录

可以通过游标的Cursor.getNext()方法来遍历记录,Cursor.getNext()表示游标指针向下移动一条记录。同样的Cursor.getPrev()表示游标指针向上移动一条记录。

使用示例一:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.DatabaseException;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

Cursor cursor = null;

try {

cursor = myDatabase.openCursor(null, null);

DatabaseEntry foundKey = new DatabaseEntry();

DatabaseEntry foundData = new DatabaseEntry();

// 通过cursor.getNex方法来遍历记录

while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==

OperationStatus.SUCCESS) {

String keyString = new String(foundKey.getData(), "UTF-8");

String dataString = new String(foundData.getData(), "UTF-8");

System.out.println("Key | Data : " + keyString + " | " +

dataString + "");

}

} catch (DatabaseException de) {

System.err.println("Error accessing database." + de);

} finally {

// 使用后必须关闭游标

cursor.close();

}

使用示例二:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.DatabaseException;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

Cursor cursor = null;

try {

...

// Open the cursor.

cursor = myDatabase.openCursor(null, null);

DatabaseEntry foundKey = new DatabaseEntry();

DatabaseEntry foundData = new DatabaseEntry();

// 使用cursor.getPrev方法来遍历游标获取数据

while (cursor.getPrev(foundKey, foundData, LockMode.DEFAULT)

== OperationStatus.SUCCESS) {

String theKey = new String(foundKey.getData(), "UTF-8");

String theData = new String(foundData.getData(), "UTF-8");

System.out.println("Key | Data : " + theKey + " | " + theData + "");

}

} catch (DatabaseException de) {

System.err.println("Error accessing database." + de);

} finally {

// 使用后必须关闭游标

cursor.close();

}

l 搜索数据

你可以通过游标方式搜索你的database记录,你也可以通过一个key来搜索你的记录,同样的你也可以通过key和value组合在一起来搜索记录。如果查询失败,则游标会返回OperationStatus.NOTFOUND。

游标支持都检索方法如下:

1) Cursor.getSearchKey()

通过key的方式检索,使用后游标指针将移动到跟当前key匹配的第一项。

2) Cursor.getSearchKeyRange()

把游标移动到大于或等于查询的key的第一个匹配key,大小比较是通过你设置的比较器来完成的,如果没有设置则使用默认的比较器。

3) Cursor.getSearchBoth()

通过key和value方式检索,然后把游标指针移动到与查询匹配的第一项。

4) Cursor.getSearchBothRange()

把游标移动到所有的匹配key和大于或等于指定的data的第一项。

比如说database存在如下的key/value记录,,大小比较是通过你设置的比较器来完成的,如果没有设置则使用默认的比较器。

假设你的database存在如下的记录。

Alabama/Athens Alabama/Florence Alaska/Anchorage Alaska/Fairbanks Arizona/Avondale Arizona/Florence然后查询

查询的key

查询的data

游标指向

Alaska

Fa

Alaska/Fairbanks

Arizona

Fl

Arizona/Florence

Alaska

An

Alaska/Anchorage

使用示例:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.DatabaseException;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

String searchKey = "Alaska";

String searchData = "Fa";

Cursor cursor = null;

try {

...

cursor = myDatabase.openCursor(null, null);

DatabaseEntry theKey =

new DatabaseEntry(searchKey.getBytes("UTF-8"));

DatabaseEntry theData =

new DatabaseEntry(searchData.getBytes("UTF-8"));

cursor = myDatabase.openCursor(null, null);

OperationStatus retVal = cursor.getSearchBothRange(theKey,

theData, LockMode.DEFAULT);

if (retVal == OperationStatus.NOTFOUND) {

System.out.println(searchKey + "/" + searchData +

" not matched in database " +

myDatabase.getDatabaseName());

} else {

String foundKey = new String(theKey.getData(), "UTF-8");

String foundData = new String(theData.getData(), "UTF-8");

System.out.println("Found record " + foundKey + "/" + foundData +

"for search key/data: " + searchKey +

"/" + searchData);

}

} catch (Exception e) {

// Exception handling goes here

} finally {

cursor.close();

}

l 使用游标来定位多重记录

如果你的库支持多重记录,你可以使用游标来遍历一个key下的多个data.

1) Cursor.getNext(), Cursor.getPrev()

获取上一条记录或下一条记录

2) Cursor.getSearchBothRange()

用语定位到满足指定data的第一条记录。

3) Cursor.getNextNoDup(), Cursor.getPrevNoDup()

跳到上一个key的最后一个data或下一个key的第一个data,忽略 当前key多重记录的存在。

4) Cursor.getNextDup(), Cursor.getPrevDup()

在当前key中把指针移动到前一个data或后一个data.

5) Cursor.count()

获取当前key下的data总数。

使用示例:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.DatabaseException;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

Cursor cursor = null;

try {

...

// Create DatabaseEntry objects

// searchKey is some String.

DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));

DatabaseEntry theData = new DatabaseEntry();

cursor = myDatabase.openCursor(null, null);

OperationStatus retVal = cursor.getSearchKey(theKey,

theData, LockMode.DEFAULT);

// 如果count超过一个,则遍历

if (cursor.count() > 1) {

while (retVal == OperationStatus.SUCCESS) {

String keyString = new String(theKey.getData(), "UTF-8");

String dataString = new String(theData.getData(), "UTF-8");

System.out.println("Key | Data : " + keyString + " | " +

dataString + "");

retVal = cursor.getNextDup(theKey, theData, LockMode.DEFAULT);

}

}

} catch (Exception e) {

// Exception handling goes here

} finally {

// Make sure to close the cursor

cursor.close();

}

l 通过游标来添加数据

你可以通过游标来向database里添加数据

你可以使用如下方法来向database里添加数据

1) Cursor.put()

如果database不存在key,则添加,如果database存在key但允许多重记录,则可以通过比较器在适当的位置插入数据,如果key已存在且不支持多重记录,则替换原有的数据。

2) Cursor.putNoDupData()

如果存在相同的key和data则返回OperationStatus.KEYEXIST.

如果不存在key则添加数据。

3) Cursor.putNoOverwrite()

如果存在相同的key在database里则返OperationStatus.KEYEXIS,

如果不存在key则添加数据。

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.OperationStatus;

...

String key1str = "My first string";

String data1str = "My first data";

String key2str = "My second string";

String data2str = "My second data";

String data3str = "My third data";

Cursor cursor = null;

try {

...

DatabaseEntry key1 = new DatabaseEntry(key1str.getBytes("UTF-8"));

DatabaseEntry data1 = new DatabaseEntry(data1str.getBytes("UTF-8"));

DatabaseEntry key2 = new DatabaseEntry(key2str.getBytes("UTF-8"));

DatabaseEntry data2 = new DatabaseEntry(data2str.getBytes("UTF-8"));

DatabaseEntry data3 = new DatabaseEntry(data3str.getBytes("UTF-8"));

cursor = myDatabase.openCursor(null, null);

OperationStatus retVal = cursor.put(key1, data1); // 添加成功

retVal = cursor.put(key2, data2); // 添加成功

retVal = cursor.put(key2, data3); // 如果允许多重记录则添加成功 //否则添加失败

} catch (Exception e) {

// Exception handling goes here

} finally {

// Make sure to close the cursor

cursor.close();

}

l 使用游标来删除记录

你可以通过调用Cursor.delete().方法来删除当前游标所指向的记录。删除后如果没有移动过指针这个时候调用Cursor.getCurrent()还是可以得到当前值的,但移动以后就不可以了。如果没有重设指针,对同一个位置多次调用删除方法,会返回OperationStatus.KEYEMPTY状态。

使用示例:

package je.gettingStarted;

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

Cursor cursor = null;

try {

...

DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));

DatabaseEntry theData = new DatabaseEntry();

cursor = myDatabase.openCursor(null, null);

OperationStatus retVal = cursor.getSearchKey(theKey, theData, LockMode.DEFAULT);

//如果date不是多重记录.

if (cursor.count() == 1) {

System.out.println("Deleting " +

new String(theKey.getData(), "UTF-8") +

"|" +

new String(theData.getData(), "UTF-8"));

cursor.delete();//删除当前记录

}

} catch (Exception e) {

// Exception handling goes here

} finally {

// Make sure to close the cursor

cursor.close();

}

l 修改当前游标所在位置的值

可以通过Cursor.putCurrent()方法来修改,这个方法只有一个参数就是将要修改的值。这个方法不能用在多重记录。

使用示例:

import com.sleepycat.je.Cursor;

import com.sleepycat.je.Database;

import com.sleepycat.je.DatabaseEntry;

import com.sleepycat.je.LockMode;

import com.sleepycat.je.OperationStatus;

...

Cursor cursor = null;

try {

...

DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));

DatabaseEntry theData = new DatabaseEntry();

cursor = myDatabase.openCursor(null, null);

OperationStatus retVal = cursor.getSearchKey(theKey, theData,

LockMode.DEFAULT);

//将要被替换的值

String replaceStr = "My replacement string";

DatabaseEntry replacementData =

new DatabaseEntry(replaceStr.getBytes("UTF-8"));

cursor.putCurrent(replacementData);//把当前位置用新值替换

} catch (Exception e) {

// Exception handling goes here

} finally {

// Make sure to close the cursor

cursor.close();

}

 

 

 

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

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

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

分享到:
评论

相关推荐

    Berkeley DB Java Edition (JE)

    Berkeley DB Java Edition (JE) 官方7.5.11下载版本。 相关介绍 https://blog.csdn.net/hadues/article/details/80854288

    Berkeley DB Java Edition

    **Berkeley DB Java Edition**,简称BDBJE,是由Oracle公司开发的一款高度可移植的、基于文件系统的数据存储解决方案,特别适用于需要高效、可靠且无服务器的数据管理的应用场景。这款数据库系统采用B+树作为其核心...

    Berkeley DB Java Edition 5.0.73

    **Berkeley DB Java Edition 5.0.73** Berkeley DB Java Edition(简称BDB JE)是一款由Oracle公司开发的高性能、轻量级的NoSQL数据库系统。它以其高效能、可扩展性和可靠性在处理大规模数据存储时受到广泛欢迎,...

    Berkeley DB Java Edition学习报告

    Berkeley DB Java Edition (JE) 是一款开源的嵌入式数据库管理系统,由Sleepycat Software开发,现归Oracle公司所有。这款数据库系统以其键值(K/V)存储模型为特色,适用于需要高性能、可伸缩性及事务处理能力的应用...

    Berkeley_DB_Java_Edition_使用手册

    ### Berkeley DB Java Edition 使用手册详解 #### 一、Berkeley DB Java Edition (JE) 概述 Berkeley DB Java Edition (简称 JE) 是一款高性能、轻量级的NoSQL数据库解决方案,完全基于Java语言开发。它特别适用于...

    Berkeley DB Java Edition数据结构的研究与应用.pdf

    Berkeley DB Java Edition(JE)是一种为Java程序提供内嵌式、事务保护的数据库引擎,它继承了Berkeley DB家族的优点,包括快速、可靠和具备容错能力的数据管理特性。为了深入理解其数据存储结构,有必要对JE使用的B...

    Berkeley DB Java Edition 4.1.10.zip

    Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。 能够高效率的处理1到1百万条记录,制约JE数据库的往往是硬件系统,而不是JE本身。 多线程支持,JE使用超时的方式来处理...

    Berkeley DB的java版本

    Berkeley DB Java Edition JE 是一个完全用JAVA写的 它适合于管理海量的 简单的数据 能够高效率的处理1到1百万条记录 制约JE数据库的往往是硬件系统 而不是JE本身 多线程支持 JE使用超时的方式来处理线程间的死琐...

    Berkeley DB Java Edition 4.0.92 开发包

    《Berkeley DB Java Edition 4.0.92 开发包详解》 Berkeley DB Java Edition(简称BDB JE)是Oracle公司推出的一款强大的、高度可定制的嵌入式数据库系统,尤其适用于Java应用程序。这款数据库引擎以其轻量级、高...

    Java嵌入式NoSQL数据库之Berkeley DB Java Edition

    **Java嵌入式NoSQL数据库之Berkeley DB Java Edition** Berkeley DB Java Edition(简称BDB JE)是一种高性能、轻量级的嵌入式数据库系统,由Oracle公司开发,广泛应用于需要快速数据存储和检索的应用场景。它并非...

    Berkeley DB Java Edition初步

    NULL 博文链接:https://xpenxpen.iteye.com/blog/2124921

    BerkeleyDB_java_jar包

    3. **示例和文档**:可能包含演示如何使用BerkeleyDB Java API的示例代码,以及详细说明如何配置、操作和管理数据库的文档。 4. **依赖库**:BerkeleyDB可能依赖于其他的Java库,这些库也可能包含在jar文件中或者...

    berkeley db java

    自己稍微封装了一下,可以当成简单的map来使用。

    嵌入式Berkeley DB Java版与Derby技术研究.pdf

    《嵌入式Berkeley DB Java版与Derby技术研究》一文主要探讨了两种典型的嵌入式数据库技术——Berkeley DB Java Edition和Apache Derby。嵌入式数据库在资源有限的环境中,如嵌入式系统,因其体积小、功能齐全、可...

    Java-Edition-BerkeleyDB-3.1.0.zip_BerkeleyDB

    在Java-Edition-BerkeleyDB-3.1.0版本中,它提供了高效、可靠的数据存储解决方案,尤其适合于对性能有极高要求的嵌入式应用或分布式系统。该数据库系统以其轻量级、无服务器模式以及出色的并发控制而闻名。 **1. ...

    Berkeley DB 读取样例

    总的来说,Berkeley DB Java Edition为Java开发者提供了一种快速、可靠且灵活的本地数据存储解决方案。通过上述步骤,我们可以创建并管理Berkeley DB数据库,实现数据的存取。然而,为了充分利用其功能,还需要深入...

    Berkeley_DB_Java_Edition.zip_海量 数据

    Berkeley DB Java Edition (JE)是一个完全用JAVA 写的,它适合于管理海量的,简单的 数据。 l 能够高效率的处理 1 到 1 百万条记录,制约 JE 数据库的往往是硬件系统,而不是 JE 本身。 多线程支持,JE 使用超时的...

Global site tag (gtag.js) - Google Analytics