Berkeley DB Java Edition (JE)

本文介绍JE数据库的基础使用方法,包括数据库环境配置、属性设置、基本操作等,并提供示例代码,帮助开发者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 String(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
   }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值