Wrapping and Extending the LevelDB Java API with Custom Features
This article demonstrates how to encapsulate the native LevelDB Java API into a reusable class, adds support for integer values and Redis‑like operations such as increment, decrement, append, and cut, and provides complete code examples for the extended functionality.
In the previous post I introduced a LevelDB Java & Go practice; this time I wrap the native LevelDB API into a custom class and extend it to behave more like Redis, supporting integer values and additional operations.
Encapsulation
The wrapper follows the previous base‑object approach: each LevelDB instance is represented by a custom class, providing methods that hide the conversion between String and byte[]. This reduces boilerplate and makes the code cleaner.
<code class="language-java">/**
* LevelDB database operation class
*/
class LevelBase extends SourceCode {
static Iq80DBFactory factory = Iq80DBFactory.factory;
static Options options = new Options();
DB db;
/**
* Create object
* @param path
*/
LevelBase(String path) {
db = factory.open(new File(getLongFile(path)), options);
}
/**
* Get value
* @param key
* @return
*/
def get(String key) {
new String(db.get(bytes(key)), DEFAULT_CHARSET);
}
/**
* Store data
* @param key
* @param value
* @return
*/
def put(String key, String value) {
db.put(bytes(key), bytes(value));
}
/**
* Delete a value
* @param key
* @return
*/
def del(String key) {
db.delete(bytes(key));
}
/**
* Get all keys
* @return
*/
def keys() {
def keys = [];
DBIterator iterator = db.iterator();
while (iterator.hasNext()) {
Map.Entry<byte[], byte[]> next = iterator.next();
keys << next.key;
}
return keys;
}
/**
* Close
* @return
*/
def close() {
db.close();
}
}
</code>Feature Extension
To support integer values, the wrapper adds conversion between int and String. Inspired by com.funtester.db.redis.RedisBase, additional methods such as incr, decr, add, minus, append, and cut are implemented, all handling the necessary String / byte[] conversions. Increment/decrement methods are synchronized to avoid thread‑safety issues during performance testing.
<code class="language-groovy">/**
* Get int value
* @param key
* @return
*/
def getInt(String key) {
return changeStringToInt(get(key));
}
/**
* Append content to existing value
* @param key
* @param content
* @return
*/
def append(String key, String content) {
put(key, get(key) + content);
}
/**
* Remove a fragment from existing value
* @param key
* @param content
* @return
*/
def cut(String key, String content) {
put(key, get(key) - content);
}
/**
* Put int value
* @param key
* @param value
* @return
*/
def putInt(String key, int value) {
db.put(bytes(key), bytes(value + EMPTY));
}
/**
* Increment
* @param key
* @return
*/
def incr(String key) {
add(key, 1);
}
/**
* Decrement
* @param key
* @return
*/
def decr(String key) {
minus(key, 1);
}
/**
* Add i to value
* @param key
* @param i
* @return
*/
def add(String key, int i) {
synchronized (this) {
putInt(key, getInt(key) + i);
}
}
/**
* Subtract i from value
* @param key
* @param i
* @return
*/
def minus(String key, int i) {
add(key, -i);
}
</code>This post shares the Java implementation and extensions; the next post will cover the Go implementation and several testing scenarios for LevelDB. Stay tuned to FunTester for more.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
