`
treemp3
  • 浏览: 23817 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

一个极其轻量级的小巧的Key/Value数据库(NOSQL)

阅读更多
新写的一个Java Key/Value数据库,有些NOSQL的意思,呵呵。跟大家共享出来,小弟是个新手,请不要拍的太厉害,谢谢!
程序比较轻量级,非常的小巧,只有一个Java类文件。在实用中对于比较简单的数据结构,用起来还是比较方便的,性能也好。
使用的时候有个前提,那就是要有Servlet容器(引擎)即可。类代码如下:
package cn.treemp3.db;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedHashMap;
import javax.servlet.ServletContext;

/**
 * 基于内存+文件的NOSQL数据库类。
 * <p>此类利用了Servlet容器中application对象的常驻内存的特性、LinkedHashMap对象的key/value特性,以及对象序列化技术。</p>
 * <p>数据库初始化时首先读取内存数据对象,对象若存在,则返回该对象;若不存在,将读取硬盘数据文件。<br />
 * 数据文件若存在,返回使用该文件生成的内存数据对象;若不存在,返回新创建的空的内存数据对象。</p>
 * <p>内存中的数据对象更新达到一定次数后,将数据同步至至数据文件,同时对象的更新次数重新开始计数。</p>
 * <p>数据的插入、更新、查询全部在内存中完成。</p>
 * <p>清理数据库的步骤为(1)清理数据文件,(2)清理内存数据对象。</p>
 * @author yangfusheng
 * @version 2.0
 */
public class FileDB2 {
    private String dbName = "/filedb/test.db"; //数据库表文件名
    private ServletContext dbApp; //当前应用(application对象)
    /**
     * @param dbName 数据库表文件名,前面可加数据库文件路径,如:“/pc/client/download.db”。
     * @param dbApp 当前应用(application对象),页面中可以通过getServletConfig().getServletContext()方法获得
     */
    public FileDB2(String dbName, ServletContext dbApp) {
        this.dbName = dbName;
        this.dbApp = dbApp;
        if (dbApp.getAttribute(dbName) == null) init(); //读取磁盘文件
    }
    /**读取磁盘文件,生成内存数据对象*/
    private void init() {
        File file = new File(dbApp.getRealPath(dbName));
        if (file.exists()) {//文件存在,反序列化为LinkedHashMap对象
            ObjectInputStream ois = null;
            try {//反序列化为LinkedHashMap对象
                ois = new ObjectInputStream(new FileInputStream(file));
                dbApp.setAttribute(dbName, (LinkedHashMap) ois.readObject());
                ois.close();
            } catch (Exception e) {
                dbApp.setAttribute(dbName, new LinkedHashMap<String, String>());
                System.out.println(e);
            }
        } else {//文件不存在,创建空的LinkedHashMap对象
            dbApp.setAttribute(dbName, new LinkedHashMap<String, String>());
            file.getParentFile().mkdirs();
        }
    }
    /**查询整个表*/
    public LinkedHashMap select() {
        return (LinkedHashMap) dbApp.getAttribute(dbName);
    }
    /**查询一条记录*/
    public String select(String key) {
        LinkedHashMap dbTable = (LinkedHashMap) dbApp.getAttribute(dbName);
        return (String) dbTable.get(key);
    }
    /**插入或更新记录*/
    public void update(String key, String value) {
        ((LinkedHashMap) dbApp.getAttribute(dbName)).put(key, value);
        upCount();
    }
    /**删除记录*/
    public void delete(String key) {
        ((LinkedHashMap) dbApp.getAttribute(dbName)).remove(key);
        upCount();
    }
    /**计数器方法*/
    private void upCount() {
        if (dbApp.getAttribute(dbName + "_count") == null) {
            dbApp.setAttribute(dbName + "_count", new Integer(0));
        }
        int dbCount = (Integer) dbApp.getAttribute(dbName + "_count");
        dbApp.setAttribute(dbName + "_count", new Integer(dbCount + 1));//计数器增加1次
        if (dbCount > 1000) {//累计达到1000次时,保存至文件,计数器清零
            save();
            dbApp.setAttribute(dbName + "_count", new Integer(0));
        }
    }
    /**保存内存数据对象至磁盘文件*/
    public void save() {
        ObjectOutputStream oos = null;
        try {//序列化内存数据对象
            oos = new ObjectOutputStream(new FileOutputStream(dbApp.getRealPath(dbName)));
            oos.writeObject((LinkedHashMap) dbApp.getAttribute(dbName));
            oos.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    /**清除内存数据对象*/
    public void delCache() {
        dbApp.removeAttribute(dbName);
        dbApp.removeAttribute(dbName + "_count");
        dbApp = null;
    }
    /**清除磁盘数据文件*/
    public void delFile() {
        File file = new File(dbApp.getRealPath(dbName));
        if (file.isFile() && file.exists()) file.delete();
    }
}

同时写了用于两个页面测试和管理的JSP文件,admin.jsp代码如下:
<%@ page contentType="text/html; charset=utf-8" %>
<%
String mode = request.getParameter("mode");
if (mode == null) mode = "0";
String table = request.getParameter("table");
if (table == null) table = "/filedb/test2.db";

javax.servlet.ServletContext app = getServletConfig().getServletContext();
cn.treemp3.db.FileDB2 db = new cn.treemp3.db.FileDB2(table, app);

switch (Integer.parseInt(mode)) {
    case 1 : break;
    case 2 :
        db.update("ceshi11", "测试12");
        db.update("测试21", "ceshi22");
        db.update("ceshi31", "ceshi32");
        db.update("测试41", "测试42");
        //db.update("ceshi31", "覆盖32");
        break;
    case 3 :
        java.util.LinkedHashMap<String, String> map = db.select();
        for (String value : map.values()) {
            out.println(value + "<br />");
        }
        break;
    case 4 :
        out.println("Key : ceshi11, value : " + db.select("ceshi11") + "<br />");
        out.println("Key : 测试21, value : " + db.select("测试21") + "<br />");
        out.println("Key : ceshi31, value : " + db.select("ceshi31") + "<br />");
        out.println("Key : 测试41, value : " + db.select("测试41") + "<br />");
        break;
    case 5 :
        db.save();
        break;
    case 6 :
        db.delCache();
        break;
    case 7 :
        db.delFile();
        break;
    case 8 :
        db.delete("测试21");
        break;
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件数据库管理</title>
</head>

<body>
<p>文件数据库管理:</p>
<form id="form1" method="post" action="">
    <input type="button" name="Submit2" value="加入测试数据(内存)" onclick="location.href='admin.jsp?mode=2'" />
    <input type="button" name="Submit3" value="查询数据(方式一)" onclick="location.href='admin.jsp?mode=3'" />
    <input type="button" name="Submit7" value="查询数据(方式二)" onclick="location.href='admin.jsp?mode=4'" />
    <input type="button" name="Submit4" value="保存内存数据对象至硬盘" onclick="location.href='admin.jsp?mode=5'" />
    <input type="button" name="Submit5" value="清理内存数据对象" onclick="location.href='admin.jsp?mode=6'" />
    <input type="button" name="Submit8" value="清理硬盘数据文件" onclick="location.href='admin.jsp?mode=7'" />
    <input type="button" name="Submit9" value="删除一条记录" onclick="location.href='admin.jsp?mode=8'" />
</form>
<p>此类利用了Servlet容器中application对象的常驻内存的特性、LinkedHashMap对象的key/value特性,以及对象序列化技术。</p>
<p>数据库初始化时首先读取内存数据对象,对象若存在,则返回该对象;若不存在,将读取硬盘数据文件。<br />
数据文件若存在,返回使用该文件生成的内存数据对象;若不存在,返回新创建的空的内存数据对象。</p>
<p>内存中的数据对象更新达到一定次数后,将数据同步至至数据文件,同时对象的更新次数重新开始计数。</p>
<p>数据的插入、更新、查询全部在内存中完成。</p>
<p>清理数据库的步骤为(1)清理数据文件,(2)清理内存数据对象。</p>
</body>
</html>

admin2.jsp代码如下:
<%@ page contentType="text/html; charset=utf-8" %>
<%
String mode = request.getParameter("mode");
if (mode == null) mode = "0";
javax.servlet.ServletContext app = getServletConfig().getServletContext();
switch (Integer.parseInt(mode)) {
    case 9 :
        for (java.util.Enumeration<String> e = app.getAttributeNames(); e.hasMoreElements();) {
            String next = e.nextElement();
            if (next.indexOf("_count") != -1) out.println("表名:" + next.replaceAll("_count", "") + ",更新次数:" + app.getAttribute(next) + "次。<br />");
        }
        break;
    case 10 :
        for (java.util.Enumeration<String> e = app.getAttributeNames(); e.hasMoreElements();) {
            String next = e.nextElement();
            if (next.indexOf("_count") != -1) {
                cn.treemp3.db.FileDB2 db = new cn.treemp3.db.FileDB2(next.replaceAll("_count", ""), app);
                db.save();
                app.setAttribute(next, new Integer(0));
            }
        }
        break;
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件数据库管理</title>
</head>

<body>
<p>文件数据库管理2:</p>
<form id="form1" method="post" action="">
    <input type="button" name="Submit10" value="查看全部数据库表" onclick="location.href='admin2.jsp?mode=9'" />
    <input type="button" name="Submit11" value="保存全部数据至磁盘" onclick="location.href='admin2.jsp?mode=10'" />
</form>
<p>此页面是针对所有数据库的查看、保存操作。</p>
</body>
</html>

附件里是源代码,直接用netbeans可以打开。
1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics