2012-09-16 23 views
0

我有一個伯克利db數據庫,其中'鍵'和'值'的類型是整數。有沒有辦法以'value'的降序遍歷數據庫?如何以'value'的降序遍歷berkeley-db數據庫?

我正在使用Berkeley-db je-5.0.58 API。下面顯示了我從文檔中使用的示例代碼。

/*- 
* See the file LICENSE for redistribution information. 
* 
* Copyright (c) 2004-2010 Oracle. All rights reserved. 
* 
*/ 

package je; 
import java.io.File; 

import com.sleepycat.bind.tuple.IntegerBinding; 
import com.sleepycat.je.Cursor; 
import com.sleepycat.je.Database; 
import com.sleepycat.je.DatabaseConfig; 
import com.sleepycat.je.DatabaseEntry; 
import com.sleepycat.je.DatabaseException; 
import com.sleepycat.je.Environment; 
import com.sleepycat.je.EnvironmentConfig; 
import com.sleepycat.je.LockMode; 
import com.sleepycat.je.OperationStatus; 
import com.sleepycat.je.Transaction; 

/** 
* SimpleExample creates a database environment, a database, and a database 
* cursor, inserts and retrieves data. 
*/ 
class SimpleExample { 
private static final int EXIT_SUCCESS = 0; 
private static final int EXIT_FAILURE = 1; 

private int numRecords; // num records to insert or retrieve 
private int offset;  // where we want to start inserting 
private boolean doInsert; // if true, insert, else retrieve 
private File envDir; 

public SimpleExample(int numRecords, 
        boolean doInsert, 
        File envDir, 
        int offset) { 
    this.numRecords = numRecords; 
    this.doInsert = doInsert; 
    this.envDir = envDir; 
    this.offset = offset; 
} 

/** 
* Usage string 
*/ 
public static void usage() { 
    System.out.println("usage: java " + 
         "je.SimpleExample " + 
         "<dbEnvHomeDirectory> " + 
         "<insert|retrieve> <numRecords> [offset]"); 
    System.exit(EXIT_FAILURE); 
} 

/** 
* Main 
*/ 
public static void main(String argv[]) { 

    if (argv.length < 2) { 
     usage(); 
     return; 
    } 
    File envHomeDirectory = new File(argv[0]); 

    boolean doInsertArg = false; 
    if (argv[1].equalsIgnoreCase("insert")) { 
     doInsertArg = true; 
    } else if (argv[1].equalsIgnoreCase("retrieve")) { 
     doInsertArg = false; 
    } else { 
     usage(); 
    } 

    int startOffset = 0; 
    int numRecordsVal = 0; 

    if (doInsertArg) { 

     if (argv.length > 2) { 
      numRecordsVal = Integer.parseInt(argv[2]); 
     } else { 
      usage(); 
      return; 
     } 

     if (argv.length > 3) { 
      startOffset = Integer.parseInt(argv[3]); 
     } 
    } 

    try { 
     SimpleExample app = new SimpleExample(numRecordsVal, 
               doInsertArg, 
               envHomeDirectory, 
               startOffset); 
     app.run(); 
    } catch (DatabaseException e) { 
     e.printStackTrace(); 
     System.exit(EXIT_FAILURE); 
    } 
    System.exit(EXIT_SUCCESS); 
} 

/** 
* Insert or retrieve data 
*/ 
public void run() throws DatabaseException { 
    /* Create a new, transactional database environment */ 
    EnvironmentConfig envConfig = new EnvironmentConfig(); 
    envConfig.setTransactional(true); 
    envConfig.setAllowCreate(true); 
    Environment exampleEnv = new Environment(envDir, envConfig); 

    /* 
    * Make a database within that environment 
    * 
    * Notice that we use an explicit transaction to 
    * perform this database open, and that we 
    * immediately commit the transaction once the 
    * database is opened. This is required if we 
    * want transactional support for the database. 
    * However, we could have used autocommit to 
    * perform the same thing by simply passing a 
    * null txn handle to openDatabase(). 
    */ 
    Transaction txn = exampleEnv.beginTransaction(null, null); 
    DatabaseConfig dbConfig = new DatabaseConfig(); 
    dbConfig.setTransactional(true); 
    dbConfig.setAllowCreate(true); 
    dbConfig.setSortedDuplicates(true); 
    Database exampleDb = exampleEnv.openDatabase(txn, 
               "simpleDb", 
               dbConfig); 
    txn.commit(); 

    /* 
    * Insert or retrieve data. In our example, database records are 
    * integer pairs. 
    */ 

    /* DatabaseEntry represents the key and data of each record */ 
    DatabaseEntry keyEntry = new DatabaseEntry(); 
    DatabaseEntry dataEntry = new DatabaseEntry(); 

    if (doInsert) { 

     /* put some data in */ 
     for (int i = offset; i < numRecords + offset; i++) { 
      /* 
      * Note that autocommit mode, described in the Getting 
      * Started Guide, is an alternative to explicitly 
      * creating the transaction object. 
      */ 
      txn = exampleEnv.beginTransaction(null, null); 

      /* Use a binding to convert the int into a DatabaseEntry. */ 

      IntegerBinding.intToEntry(i, keyEntry); 
      IntegerBinding.intToEntry(i+1, dataEntry); 
      OperationStatus status = 
       exampleDb.put(txn, keyEntry, dataEntry); 

      /* 
      * Note that put will throw a DatabaseException when 
      * error conditions are found such as deadlock. 
      * However, the status return conveys a variety of 
      * information. For example, the put might succeed, 
      * or it might not succeed if the record alread exists 
      * and the database was not configured for duplicate 
      * records. 
      */ 
      if (status != OperationStatus.SUCCESS) { 
       throw new RuntimeException("Data insertion got status " + 
              status); 
      } 
      txn.commit(); 
     } 
    } else { 
     /* retrieve the data */ 
     Cursor cursor = exampleDb.openCursor(null, null); 

     while (cursor.getNext(keyEntry, dataEntry, LockMode.DEFAULT) == 
       OperationStatus.SUCCESS) { 
      System.out.println("key=" + 
           IntegerBinding.entryToInt(keyEntry) + 
           " data=" + 
           IntegerBinding.entryToInt(dataEntry)); 

     } 
     cursor.close(); 
    } 

    exampleDb.close(); 
    exampleEnv.close(); 

    } 
} 
+0

能否提供更多細節?您使用哪種Berkeley-db Java API?你有一些示例代碼? – IceMan

+0

請參閱上文,我已更新該問題。 – user1444462

回答

0

可以使用custom comparator並使用cursor遍歷降序排列數據。

在你要實現自定義的java比較:

編輯

import java.util.Comparator; 

import com.sleepycat.bind.tuple.IntegerBinding; 
import com.sleepycat.je.DatabaseEntry; 

public class IntegerSorter implements Comparator<byte[]> 
    { 
    @Override 
    public int compare(byte[] o1, byte[] o2) 
     { 
     return 
       IntegerBinding.entryToInt(new DatabaseEntry(o1)) - 
       IntegerBinding.entryToInt(new DatabaseEntry(o2)); 
     } 
    } 

(...) 
dbConfig.setBtreeComparator(IntegerSorter.class); 
(...) 
+0

感謝您的及時回覆。按照您的建議使用自定義比較器後,程序編譯時不會出現任何錯誤。但是我在運行時遇到以下異常: 線程「main」中的異常java.lang.IllegalArgumentException:Btree比較器無效。也許你沒有爲比較器實現零參數構造函數,或者找不到比較器類。 我試圖谷歌它,但找不到任何解決方案。 :( – user1444462

+0

整個數據庫必須使用比較器從頭開始構建,不能建立/填充數據庫,然後添加此比較器。 – Pierre

+0

在編譯之前,我已經刪除了所有以前的數據庫和類文件,但它仍然會給出相同的錯誤。 – user1444462