Databases 6 min read

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.

FunTester
FunTester
FunTester
Wrapping and Extending the LevelDB Java API with Custom Features

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.

/**
 * 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
next = iterator.next();
            keys << next.key;
        }
        return keys;
    }

    /**
     * Close
     * @return
     */
    def close() {
        db.close();
    }
}

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.

/**
 * 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);
}

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.

JavaCode ExampleLevelDBKey-Value StoreDatabase Wrapper
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.