package test;
import com.sleepycat.je.*;
import com.sleepycat.bind.EntryBinding;
import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.serial.StoredClassCatalog;
import com.sleepycat.bind.serial.SerialBinding;
import java.io.File;
public class test {
public static void main(String[] args) {
}
/**
* 打開和關閉環境,示例一
*
*/
public void eg1(){
//----打開環境,如果不存在,則創建一個------------
Environment myDbEnvironment=null;
try {
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true); //true不存在就創建,false如果不存在則打開環境失敗
//envConfig.setReadOnly(true); //true 以只讀方式打開,如果是多進程應用,每個進程都要設置爲true
//envConfig.setTransactional(true);//true支持事務,false不支持,默認false。可以更改配置文件來設置此參數。
myDbEnvironment = new Environment(new File(".//"), envConfig);//環境所在路徑
java.util.List myDbNames = myDbEnvironment.getDatabaseNames(); //得到所有的數據庫的名字
for(int i=0; i < myDbNames.size(); i++) {
System.out.println("Database Name: " + (String)myDbNames.get(i));
}
} catch (DatabaseException dbe) {
// 錯誤處理
}
//----關閉環境----------------
try {
if (myDbEnvironment != null) {
myDbEnvironment.cleanLog(); //在關閉前也最好執行一下cleaner,清理一下日誌文件,因爲delete操作會浪費一些空間
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
// 錯誤處理
}
}
/**
* 打開環境示例二
*
*/
public void eg2()
{
Environment myEnv = null;
try{
myEnv=new Environment(new File("/export/dbEnv"), null);
EnvironmentMutableConfig envMutableConfig = new EnvironmentMutableConfig();
envMutableConfig.setCachePercent(50);//設置je的cache佔用jvm 內存的百分比。
//envMutableConfig.setCacheSize(123456);//設定緩存的大小爲123456Bytes
envMutableConfig.setTxnNoSync(true);//設定事務提交時是否寫更改的數據到磁盤,true不寫磁盤。
//envMutableConfig.setTxnWriteNoSync(false);//設定事務在提交時,是否寫緩衝的log到磁盤。如果寫磁盤會影響性能,不寫會影響事務的安全。隨機應變。
myEnv.setMutableConfig(envMutableConfig);
EnvironmentStats envStats=myEnv.getStats(null);//調用 Environment.getStats() 返回一個EnvironmentStas對象。調用EnvironmentStats.getNCacheMiss()看命不中數。
long cacheMisses = envStats.getNCacheMiss(); //這個統計非常重要,尤其針對於長時間運行的應用。 它返回不能夠在內存中命中的請求總數,這可以用來參考指定cache的大小。
//myEnv.getMutableConfig();//得到當前的環境配置信息
}catch(DatabaseException dbe){}
}
/**
* 打開database,以及相關操作
*
*/
public void eg3(){
Environment myDbEnvironment = null;
Database myDatabase = null;
try {
// Open the environment. Create it if it does not already exist.
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig); //也可能用DatabaseConfig參數來打開,這樣就可以設置數據庫的屬性,比如是否允許在庫不存在時創建它,是否只讀打開,是否支持事務等。
// Open the database. Create it if it does not already exist.
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
//transaction爲null,不支持事務
myDatabase = myDbEnvironment.openDatabase(null,"sampleDatabase",dbConfig); //打開庫,要提供一個數據庫名字作爲參數
} catch (DatabaseException dbe) {
// Exception handling goes here
}
//記錄
String aKey = "key";
String aData = "data";
try {
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));//最好指定編碼方式,因爲不指定編碼會用系統的默認編碼來轉換,因爲系統的默認編碼可能會被人更改。
DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
byte[] myKey = theKey.getData();
byte[] myData = theData.getData();
//從byte數組轉換爲string的方法
String key = new String(myKey, "UTF-8");
String data = new String(myData, "UTF-8");
//get和put用在非重複的數據存儲,讀寫庫時,注意一個小區別,就是數據庫,是否允許重複的記錄存在,兩個記錄公用一個key,這就是重複的記錄,我們把重複的記錄成爲重複集合。或者叫多重。
//遊標用於重複數據存儲put和get。
//數據記錄在內部是用Btree按照特定排序來存儲的。一般是用key來排序的,key相同的多重數據是按照data來排序。
//記錄Using Database Records
//記錄是由key和data組成,即所熟悉的key->value,二者都被是有DatabaseEntry封裝的。
//這個之前也提過很多次了,DatabaseEntry可以封裝原始類型和複雜的對象類型,二者都要被轉換爲byte array存儲,轉換可以使用Bind API來完成
//寫數據
myDatabase.put(null, theKey, theData);//如果不是可重複數據庫,put將會覆蓋原有的記錄。
//myDatabase.putNoOverwrite(null, theKey, theData);//不允許覆蓋,不管是否允許數據重複。
//讀數據
//--myDatabase.getSearchBoth(null, theKey, theData, LockMode.DEFAULT);//查找key和data都匹配的記錄
//--查詢出來的key和data都是byte數組形式。
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 + "'.");
}
//刪除數據
myDatabase.delete(null, theKey); //刪除數據
} catch (Exception e) {}
//關閉數據庫
//如果打開了遊標,關閉時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
}
}
/**
* Deferred Write Databases 緩衝寫庫
*
* By默認,JE的數據庫是持久化,意思就是說不緩存,寫庫的,這樣多個應用都可以使用,把數據庫設置成非持久化的,就成爲緩衝寫庫。
* 緩衝寫庫本質上說就是內存級數據庫,這適用於那些臨時的操作。比如把oracle中的數據導入bdb,然後讀bdb cache。
* 緩衝寫庫並不是總是請求磁盤I/O,很重要的一點,緩衝寫庫會在內存不夠用的時候寫磁盤。如果內存夠大,用緩存寫庫那是最好不過了。
* 調用Database.sync()讓修改過的cache數據寫到磁盤
* 當重新打開一個緩衝寫庫的環境時,數據庫的狀態是和上一次sync時一致的。如果緩衝寫庫沒有同步,就會當成是空庫。問號,那麼在數據關閉之前一定要sync?maybe yes。
* 程序員很容易就可以把緩衝寫庫的修改存儲到磁盤上,對經常性的修改,增加,及刪除等等的操作的應用也很有用處。通過延遲寫庫,延遲了磁盤IO, 這可以提高數據的流量。
* 注意,當沒有調用sync的庫關閉時而且環境也關閉的時候,cache的修改會丟失。如果沒有關閉環境,所有的cache的修改還是會保留的。
* 設置庫爲defered or not,然後用DatabaseConfig的選項打開庫。
*/
public void eg4(){
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); //設置允許創建與否,默認值是false,打開不存在的數據庫會報錯。true的時候,數據庫不存在就創建。
//dbConfig.setBtreeComparator();//設置B樹比較器,用來比較兩個記錄的key是否相同。
//dbConfig.setDuplicateComparator();//設置允許key重複的比較器。
dbConfig.setSortedDuplicates(false);//設置爲true,允許key重複,false的話,put一個存在key的記錄會產生錯誤。如果使用了關聯了多個索引則一定不能支持重複的記錄。
//dbConfig.setExclusiveCreate(false);//如果true,只能創建,如果存在,則打開失敗If true, the database open fails if the database currently exists. That is, the open must result in the creation of a new database. Default is false.
//dbConfig.setReadOnly(true);//設置是否只讀
//dbConfig.setTransactional(true);//設置是否支持事務
dbConfig.setDeferredWrite(true); //true爲進行緩衝寫庫,false則不進行緩衝寫庫
myDatabase = myDbEnvironment.openDatabase(null,"sampleDatabase",dbConfig);
String dbName = myDatabase.getDatabaseName();//得到數據庫的名字
Environment theEnv = myDatabase.getEnvironment();//得到當前數據庫環境
myDatabase.preload(1024*1024); //預先加載數據到內存,long型參數表示要裝載到內存的數據的最大數
//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);
//存儲long類型的數據
myDatabase.put(null, theKey, theData);
OperationStatus retVal = myDatabase.get(null, theKey, theData,LockMode.DEFAULT);String retKey = null;
if (retVal == OperationStatus.SUCCESS) {
//取得long類型的數據
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
}
//implements Serializable 的對象的存儲
try {
String aKey = "myLong";
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
//寫對象
java.util.Vector data2Store = new java.util.Vector(); //假設他是implements Serializable
StoredClassCatalog classCatalog = new StoredClassCatalog(myDatabase);
EntryBinding dataBinding = new SerialBinding(classCatalog, java.util.Vector.class);//指定類型
DatabaseEntry theData = new DatabaseEntry();
dataBinding.objectToEntry(data2Store, 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
}
//做一些處理
myDatabase.sync(); //當寫完一定量的數據以後,同步要硬盤中
} catch (DatabaseException dbe) {
// Exception handling goes here
}
//關閉數據庫
try {
if (myDatabase != null) {
myDatabase.close();
}
if (myDbEnvironment != null) {
myDbEnvironment.close();
}
} catch (DatabaseException dbe) {
// Exception handling goes here
}
}
/**
* Data Persistence 持久化
* 如果是在內存中修了數據,需要寫到磁盤。
* 怕因爲系統錯誤引發數據丟失,可以使用transaction,每commit一次,修改都會被保存。
* 只是用來存放應用臨時數據的話,就不需要用transaction了。
* 在每次關閉env的時候會執行,也可以在程序中調用執行。
*/
}
/**
* 特殊對象間的自定義轉換
*
*/
/*
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 {
// Write a MyData2 object to a TupleOutput
public void objectToEntry(Object object, TupleOutput to) {
MyData2 myData = (MyData2)object;
// Write the data to the TupleOutput (a DatabaseEntry).
// Order is important. The first data written will be
// the first bytes used by the default comparison routines.
to.writeDouble(myData.getDouble().doubleValue());
to.writeLong(myData.getLong());
to.writeString(myData.getString());
}
// Convert a TupleInput to a MyData2 object
public Object entryToObject(TupleInput ti) {
// Data must be read in the same order that it was
// originally written.
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;
}
}
//==================================
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 myKey = new DatabaseEntry();
try {
// Store theKeyData in the DatabaseEntry
keyBinding.objectToEntry(theKeyData, myKey);
...
// Database put and get activity omitted for clarity
...
// Retrieve the key data
theKeyData = (MyData2) keyBinding.entryToObject(myKey);
} catch (Exception e) {
// Exception handling goes here
}
*/
//比較器
/*
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);
}
}
使用示例
package je.gettingStarted;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseException;
import java.util.Comparator;
...
// Environment open omitted for brevity
try {
// Get the database configuration object
DatabaseConfig myDbConfig = new DatabaseConfig();
myDbConfig.setAllowCreate(true);
// Set the duplicate comparator class
myDbConfig.setDuplicateComparator(MyDataComparator.class);
// Open the database that you will use to store your data
myDbConfig.setSortedDuplicates(true);
Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);
} catch (DatabaseException dbe) {
// Exception handling goes here
}
*/