您的位置:首页 > 编程语言 > Java开发

Berkeley DB Java Edition (JE)

2015-06-29 15:44 507 查看
JE 适合于管理海量的,简单的数据。其中的记录都以简单的键值对保存,即key/value对。由于它操作简单,效率较高,因此受到了广泛的好评。下面我就带领大家看看JE 是如果使用的吧~

JE 下载地址:http://www.oracle.com/technology/software/products/berkeley-db/je/index.html

下载完成解亚后,把JE_HOME/lib/je-.jar 中的jar文件添加到你的环境变量中就可以使用je了。

相关帮助文档可以参考 JE_HOME/docs/index.html

源代码见JE_HOME/src/*.*

//数据库环境
private  Environment myDbEnvironment = null;
//数据库配置
private  DatabaseConfig dbConfig=null;
//    //数据库游标
//    private  Cursor myCursor = null;
//数据库对象
private  Database myDatabase = null;
//数据库文件名
private  String fileName = "";
//数据库名称
private  String dbName = "";

设置数据库属性: 其实设置数据库属性跟设置环境属性差不多,JE中通过DatabaseConfig对象来设置数据库属性。能够设置的数据库属性如下:    

 

DatabaseConfig.setAllowCreate() 

如果是true的话,则当不存在此数据库的时候创建一个。 

 

DatabaseConfig.setBtreeComparator() 

设置用于Btree比较的比较器,通常是用来排序,用来比较两个记录的key是否相同。

 

DatabaseConfig.setDuplicateComparator() 

设置用来比较一个key有两个不同值的时候的大小比较器。 

 

DatabaseConfig.setSortedDuplicates() 

设置一个key是否允许存储多个值,true代表允许,默认false.

设置为true,允许key重复,false的话,put一个存在key的记录会产生错误。如果使用了关联了多个索引则一定不能支持重复的记录。

 

DatabaseConfig.setExclusiveCreate() 

以独占的方式打开,也就是说同一个时间只能有一实例打开这个database。如果true,只能创建,这样如果存在的话,则打开失败   

 

DatabaseConfig.setReadOnly() 

以只读方式打开database,默认是false.

 

DatabaseConfig.setTransactional() 

如果设置为true,则支持事务处理,默认是false,不支持事务。

dbConfig.setDeferredWrite(true); 

//true为进行缓冲写库,false则不进行缓冲写库

/*
* 打开当前数据库
*/
public  void openDatabase() {
// TODO Auto-generated method stub
try{
CheckMethods.PrintDebugMessage("打开数据库: "+dbName);
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
envConfig.setTransactional(true);
envConfig.setReadOnly(false);
envConfig.setTxnTimeout(10000, TimeUnit.MILLISECONDS);
envConfig.setLockTimeout(10000, TimeUnit.MILLISECONDS);
/*
*   其他配置 可以进行更改
EnvironmentMutableConfig envMutableConfig = new EnvironmentMutableConfig();
envMutableConfig.setCachePercent(50);//设置je的cache占用jvm 内存的百分比。
envMutableConfig.setCacheSize(123456);//设定缓存的大小为123456Bytes
envMutableConfig.setTxnNoSync(true);//设定事务提交时是否写更改的数据到磁盘,true不写磁盘。
//envMutableConfig.setTxnWriteNoSync(false);//设定事务在提交时,是否写缓冲的log到磁盘。如果写磁盘会影响性能,不写会影响事务的安全。随机应变。
*
*/
File file = new File(fileName);
if(!file.exists())
file.mkdirs();
myDbEnvironment = new Environment(file,envConfig);

dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
dbConfig.setTransactional(true);
dbConfig.setReadOnly(false);
//dbConfig.setSortedDuplicates(false);
/*
setBtreeComparator 设置用于B tree比较的比较器,通常是用来排序
setDuplicateComparator 设置用来比较一个key有两个不同值的时候的大小比较器。
setSortedDuplicates 设置一个key是否允许存储多个值,true代表允许,默认false.
setExclusiveCreate 以独占的方式打开,也就是说同一个时间只能有一实例打开这个database。
setReadOnly 以只读方式打开database,默认是false.
setTransactional 如果设置为true,则支持事务处理,默认是false,不支持事务。
*/
if(myDatabase == null)
myDatabase = myDbEnvironment.openDatabase(null, dbName, dbConfig);
//openDatabase中第一个参数为null,代表不支持事务
CheckMethods.PrintDebugMessage(dbName+"数据库中的数据个数: "+myDatabase.count());
/*
*  Database.getDatabaseName()
取得数据库的名称
如:String dbName = myDatabase.getDatabaseName();

Database.getEnvironment()
取得包含这个database的环境信息
如:Environment theEnv = myDatabase.getEnvironment();

Database.preload()
预先加载指定bytes的数据到RAM中。
如:myDatabase.preload(1048576l); // 1024*1024

Environment.getDatabaseNames()
返回当前环境下的数据库列表
Environment.removeDatabase()
删除当前环境中指定的数据库。
如:
String dbName = myDatabase.getDatabaseName();
myDatabase.close();
myDbEnv.removeDatabase(null, dbName);

Environment.renameDatabase()
给当前环境下的数据库改名
如:
String oldName = myDatabase.getDatabaseName();
String newName = new Strin
4000
g(oldName + ".new", "UTF-8");
myDatabase.close();
myDbEnv.renameDatabase(null, oldName, newName);

Environment.truncateDatabase()
清空database内的所有数据,返回清空了多少条记录。
如:
Int numDiscarded= myEnv.truncate(null,
myDatabase.getDatabaseName(),true);
CheckMethods.PrintDebugMessage("一共删除了 " + numDiscarded +" 条记录 从数据库 " + myDatabase.getDatabaseName());
*/
}
catch(DatabaseException e){
CheckMethods.PrintInfoMessage(e.getMessage());

}
}

/*
* 向数据库中写入String类型记录
* 传入key和value
*/
public  boolean writeToDatabase(String key,String value,boolean isOverwrite) {
// TODO Auto-generated method stub
try {
//设置key/value,注意DatabaseEntry内使用的是bytes数组
//最好指定编码方式,因为不指定编码会用系统的默认编码来转换,因为系统的默认编码可能会被人更改。

DatabaseEntry theKey=new DatabaseEntry(StringHelper.TrimString(key).getBytes("UTF-8"));
DatabaseEntry theData=new DatabaseEntry(value.getBytes("UTF-8"));
<span style="color:#FF0000;">//string和DatabaseEntry之间的相互转化</span>
//byte[] myKey = theKey.getData();
//byte[] myData = theData.getData();
//从byte数组转换为string的方法
//String key = new String(myKey, "UTF-8");
//String data = new String(myData, "UTF-8");
OperationStatus res = null; Transaction txn = null;
try {
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);

txn = myDbEnvironment.beginTransaction(null, txConfig);
if(isOverwrite) {

//get和put用在非重复的数据存储,读写库时,注意一个小区别,就是数据库,是否允许重复的记录存在,两个记录公用一个key,这就是重复的记录,我们把重复的记录成为重复集合。或者叫多重。

//游标用于重复数据存储put和get。

//数据记录在内部是用Btree按照特定排序来存储的。一般是用key来排序的,key相同的多重数据是按照data来排序。

//记录Using Database Records

//记录是由key和data组成,即所熟悉的key->value,二者都被是有DatabaseEntry封装的。

//DatabaseEntry可以封装原始类型和复杂的对象类型,二者都要被转换为byte array存储,转换可以使用Bind API来完成

res = myDatabase.put(txn, theKey, theData);//如果不是可重复数据库,put将会覆盖原有的记录。
//myDatabase.putNoOverwrite(null, theKey, theData);//不允许覆盖,不管是否允许数据重复。
} else {
res = myDatabase.putNoOverwrite(txn, theKey, theData);
}
txn.commit();
if(res == OperationStatus.SUCCESS) {
CheckMethods.PrintDebugMessage("向数据库" + dbName +"中写入:"+key+","+value);
return true;
} else if(res == OperationStatus.KEYEXIST) {
CheckMethods.PrintDebugMessage("向数据库" + dbName +"中写入:"+key+","+value+"失败,该值已经存在");
return false;
} else { CheckMethods.PrintDebugMessage("向数据库" + dbName +"中写入:"+key+","+value+"失败");
return false;
}
} catch(LockConflictException lockConflict) {
txn.abort();
CheckMethods.PrintInfoMessage("向数据库" + dbName +"中写入:"+key+","+value+"出现lock异常");
CheckMethods.PrintInfoMessage(lockConflict.getMessage());
CheckMethods.PrintInfoMessage(lockConflict.getCause().toString());
CheckMethods.PrintInfoMessage(lockConflict.getStackTrace().toString());
return false;
}
} catch (Exception e) {
// 错误处理 CheckMethods.PrintInfoMessage("向数据库" + dbName +"中写入:"+key+","+value+"出现错误");
return false;
}
}
//long类型的数据存储方法
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);

//取得long类型的数据
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
}

//存储自定义类型的数据
try {
String aKey = "student";
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));

//写对象
Student stu = new Student(); //Student类需要implements Serializable
StoredClassCatalog classCatalog = new StoredClassCatalog(myDatabase);
EntryBinding dataBinding = new SerialBinding(classCatalog, java.util.Vector.class);//指定类型
DatabaseEntry theData = new DatabaseEntry();
dataBinding.objectToEntry(stu, theData);//绑定数据
myDatabase.put(null, theKey, theData);

//读对象
myDatabase.get(null, theKey, theData, LockMode.DEFAULT);
java.util.Vector retrievedData = (java.util.Vector) dataBinding.entryToObject(theData);

} catch (Exception e) {
// Exception handling goes here
}



/*
* 关闭当前数据库
*/
public  void closeDatabase() {
// TODO Auto-generated method stub
if(myDatabase != null)
{
myDatabase.close();
}
if(myDbEnvironment != null)
{
CheckMethods.PrintDebugMessage("关闭数据库: " + dbName);
myDbEnvironment.cleanLog();
myDbEnvironment.close();
}
}

/*
* 删除数据库中的一条记录
*/
public  boolean deleteFromDatabase(String key) {
boolean success = false;
long sleepMillis = 0;
for(int i=0;i<3;i++)
{
if (sleepMillis != 0)
{
try
{
Thread.sleep(sleepMillis);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
sleepMillis = 0;
}
Transaction txn = null;
try
{
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);
txn = myDbEnvironment.beginTransaction(null, txConfig);
DatabaseEntry theKey;
theKey = new DatabaseEntry(StringHelper.TrimString(key).getBytes("UTF-8"));
OperationStatus res = myDatabase.delete(txn, theKey);
txn.commit();
if(res == OperationStatus.SUCCESS)
{
CheckMethods.PrintDebugMessage("从数据库" + dbName +"中删除:"+key);
success = true;
return success;
}
else if(res == OperationStatus.KEYEMPTY)
{
CheckMethods.PrintDebugMessage("没有从数据库" + dbName +"中找到:"+key+"。无法删除");
}
else
{
CheckMethods.PrintDebugMessage("删除操作失败,由于"+res.toString());
}
return false;
}
catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block

e.printStackTrace();
return false;
}
catch(LockConflictException lockConflict)
{
CheckMethods.PrintInfoMessage("删除操作失败,出现lockConflict异常");
CheckMethods.PrintInfoMessage(lockConflict.getMessage());
CheckMethods.PrintInfoMessage(lockConflict.getCause().toString());
CheckMethods.PrintInfoMessage(lockConflict.getStackTrace().toString());
sleepMillis = 1000;

continue;
}
finally
{
if (!success)
{
if (txn != null)
{
txn.abort();
}
}
}
}
return false;
}

--myDatabase.getSearchBoth(null, theKey, theData, LockMode.DEFAULT);//查找key和data都匹配的记录

--查询出来的key和data都是byte数组形式。


/*
* 从数据库中读出数据
* 传入key 返回value
*/
public String readFromDatabase(String key) {
// TODO Auto-generated method stub
//Database.getSearchBoth()
try {
DatabaseEntry theKey = new DatabaseEntry(StringHelper.TrimString(key).getBytes("UTF-8"));
DatabaseEntry theData = new DatabaseEntry();
Transaction txn = null;
try
{
TransactionConfig txConfig = new TransactionConfig();
txConfig.setSerializableIsolation(true);
txn = myDbEnvironment.beginTransaction(null, txConfig);
OperationStatus res = myDatabase.get(txn, theKey, theData, LockMode.DEFAULT);
txn.commit();
if(res == OperationStatus.SUCCESS)
{
byte[] retData = theData.getData();
String foundData = new String(retData, "UTF-8");
CheckMethods.PrintDebugMessage("从数据库" + dbName +"中读取:"+key+","+foundData);
return foundData;
}
else
{
CheckMethods.PrintDebugMessage("No record found for key '" + key + "'.");
return "";
}
}
catch(LockConflictException lockConflict)
{
txn.abort();
CheckMethods.PrintInfoMessage("从数据库" + dbName +"中读取:"+key+"出现lock异常");
CheckMethods.PrintInfoMessage(lockConflict.getMessage());
CheckMethods.PrintInfoMessage(lockConflict.getCause().toString());
CheckMethods.PrintInfoMessage(lockConflict.getStackTrace().toString());

return "";
}

} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();

return "";
}
}

/*
* 遍历数据库中的所有记录,返回list
*/
public  ArrayList<String> getEveryItem() {
// TODO Auto-generated method stub
CheckMethods.PrintDebugMessage("===========遍历数据库"+dbName+"中的所有数据==========");
Cursor myCursor = null;
ArrayList<String> resultList = new ArrayList<String>();
Transaction txn = null;
try{
txn = this.myDbEnvironment.beginTransaction(null, null);
CursorConfig cc = new CursorConfig();
cc.setReadCommitted(true);
if(myCursor==null)
myCursor = myDatabase.openCursor(txn, cc);
DatabaseEntry foundKey = new DatabaseEntry();
DatabaseEntry foundData = new DatabaseEntry();
// 使用cursor.getPrev方法来遍历游标获取数据
if(myCursor.getFirst(foundKey, foundData, LockMode.DEFAULT)
== OperationStatus.SUCCESS)
{
String theKey = new String(foundKey.getData(), "UTF-8");
String theData = new String(foundData.getData(), "UTF-8");
resultList.add(theKey);
CheckMethods.PrintDebugMessage("Key | Data : " + theKey + " | " + theData + "");
while (myCursor.getNext(foundKey, foundData, LockMode.DEFAULT)
== OperationStatus.SUCCESS)
{
theKey = new String(foundKey.getData(), "UTF-8");
theData = new String(foundData.getData(), "UTF-8");
resultList.add(theKey);
CheckMethods.PrintDebugMessage("Key | Data : " + theKey + " | " + theData + "");
}
}
myCursor.close();
txn.commit();
return resultList;
}
catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
catch (Exception e)
{
CheckMethods.PrintInfoMessage("getEveryItem处理出现异常");
CheckMethods.PrintInfoMessage(e.getMessage().toString());
CheckMethods.PrintInfoMessage(e.getCause().toString());

txn.abort();
if (myCursor != null)
{
myCursor.close();
}
return null;
}
}

//关闭数据库
//如果打开了游标,关闭时JE会发出警告,让你关闭他们先。活动状态的游标在关闭库的过程中会产生意想不到的结果,尤其是其他线程在写库的过程中。确定所有的访问都结束后再关闭库
try {
if (myDatabase != null) {
myDatabase.close();
myDbEnvironment.renameDatabase(null, "sampleDatabase", "test");//重命名,必须先关闭数据库
myDbEnvironment.removeDatabase(null, "sampleDatabase");//删除数据库,必须先关闭数据库
//myDbEnvironment.truncateDatabase(null, myDatabase.getDatabaseName(),true);//删除并回收数据库空间 ,true返回删除的记录的数量,false不返回删除的记录数量值
}

if (myDbEnvironment != null) {
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
// Exception handling goes here
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据库