`
treemp3
  • 浏览: 23970 次
  • 性别: 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
分享到:
评论

相关推荐

    Python-一个本地和可伸缩的键值keyvalue存储过程

    1. **SimpleDBM**: 这是一个轻量级的键值存储库,适用于简单的本地数据存储需求。它提供了一种简单的方式来保存和检索数据,而无需复杂的数据库管理系统。 2. **Redis**: 虽然Redis本身是一个服务器端的键值存储...

    cpp-OneValue高性能约100万每秒持久化KeyValue存储基于Redis协议

    2. **Key-Value存储**:这种数据结构简单直观,适合快速查找和存储,常见于缓存和轻量级数据库中。 3. **持久化**:指数据不仅存储在内存中,还会定期或在每次写入时写入磁盘,即使系统崩溃也能恢复数据。 4. **高...

    cpp-tkvdb是一个用于keyvalue数据的嵌入式数据库库

    这个数据库系统被设计成轻量级且高效,它借鉴了其他知名的键值存储解决方案,如Berkeley DB、LevelDB和SQLite4的LSM(Log-Structured Merge Tree)数据结构。tkvdb的核心目标是提供一种简单而快速的方式来存储和检索...

    NoSQL数据库笔谈

    - **Drizzle**: 轻量级的关系型数据库管理系统。 #### 五、应用篇 **1. eBay架构经验** - 介绍了eBay在分布式系统架构方面的实践经验。 **2. 淘宝架构经验** - 探讨了淘宝在高并发场景下系统的架构设计和优化。...

    Python-SHDB一个专为Shell脚本提供数据存储支持的NoSql数据

    SHDB利用Python的强大功能,为Shell脚本提供了轻量级的数据存储解决方案,适用于那些需要简单数据管理但又不想引入大型数据库系统的场景。 **核心特性** 1. **易用性**:SHDB的API设计简洁,易于理解和使用,使得...

    NoSQL数据管理技术

    Kyoto Cabinet是一个轻量级的键值数据库;Voldemort是一种分散式键值存储系统;Redis除了作为键值存储系统外,还提供了丰富的数据类型如列表(list)、集合(set)、有序集合(sorted set)等。 总之,NoSQL数据...

    simpledb:RocksDB之上的NoSQL嵌入式数据库

    3. **SQLite**:是一个轻量级的嵌入式SQL数据库,广泛应用于移动设备和桌面应用。 4. **LevelDB**:是Google开发的一个简单的键值对存储库,是`RocksDB` 的基础。 5. **Crates**:是Rust的包管理器和构建工具,帮助...

    cpp-sophia一个现代可嵌入的键值数据库

    它被设计为轻量级的解决方案,适用于那些需要快速数据存储和检索的应用场景,尤其适合在资源受限的环境中运行。Sophia的特性使其在NoSQL数据库领域中脱颖而出,下面将详细探讨其关键知识点。 1. **键值存储模型** ...

    蜂巢:用纯Dart编写的轻量级且快速的键值数据库

    蜂巢(Hive)是一个基于Dart语言的轻量级、高性能的键值数据库系统,专为现代应用程序设计。在本文中,我们将深入探讨蜂巢的核心特性、如何使用它、其与Dart和Flutter的关系,以及它在NoSQL数据存储中的作用。 1. *...

    NoSQL笔谈(颜开)

    - **4.1 亚数据库**:介绍了一些轻量级的NoSQL数据库解决方案,如MemCached、dbcached等。 - **4.2 列存系列**:涵盖了多种列式存储NoSQL数据库,如HBase、Cassandra、BigTable等。 - **4.3 非云服务竞争者**:介绍...

    cpp-FlyDB一个基于C语言实现的kv存储

    FlyDB是一个用C语言编写的轻量级键值(Key-Value)存储系统,它为开发者提供了一种高效、简单的方式来存储和检索数据。作为NoSQL数据库的一种,FlyDB不遵循传统的表格型数据库结构,而是采用键值对的形式,这使得它...

    MongoDB系列教程(一):NoSQL起源

    NoSQL的历史可以追溯到1998年,由Carlo Strozzi开发的轻量级数据库系统首次使用这个术语。然而,真正引起广泛讨论和应用是在2009年,随着Last.fm的Johan Oskarsson和Rackspace的Eric Evans提出非关系型、分布式和无...

    基于JSON的内存数据库jsonDB.zip

    它具有以下特点:轻量级. 无守护进程,无需任何额外的安装和配置,你只需要import jsonDb即可使用,非常方便.NOSQL. 类似于mongoDb的非关系型数据库.内存数据库. 所有数据基于内存进行操作和访问,性能相对较高.目前版本...

    jsonDB是一个python实现的基于JSON格式的非关系型内存数据库+源代码+文档说明

    &gt;1、轻量级. 无守护进程,无需任何额外的安装和配置,你只需要import jsonDb即可使用,非常方便. &gt;2、NOSQL. 类似于mongoDb的非关系型数据库. &gt;3、内存数据库. 所有数据基于内存进行操作和访问,性能相对较高.目前...

    owlcache::owl:owlcache是​​Go编写的轻量级,高性能,非集中式,分布式KeyValue内存缓存数据共享应用程序。 关键字:golang缓存,go缓存,golang nosql

    :owl: owlcache是​​Go编写的轻量级,高性能,非集中式,分布式键/值内存缓存数据共享应用程序(在某些情况下用作轻量级数据库)。您可以将每个节点视为单独的键/值数据您可以通过集群查询任何节点的数据,以获取...

    cpp-rlite是独立无服务器零配置事务性redis兼容的数据库引擎

    RLite是一个小巧而强大的数据库引擎,它完全兼容Redis命令,并且具有无服务器、零配置的特点,这意味着它不需要专门的服务器进程来运行,而是可以直接在本地文件系统上作为嵌入式数据库使用。这种设计使得RLite成为...

    cannondb:CannonDB是为人类创建的轻量级但功能强大的键值数据库

    CannonDB是为人类设计的轻量级但功能强大的键值数据库。 安装 pip安装cannondb 产品特点 由磁盘B树维护,因此插入/获取/删除足够快。 支持键/值的str/int/float/dict/list/UUID类型。 将数据存储在默认文件中,但...

    分布式数据库缓存系统设计与实现

    2. **Memcached**:轻量级缓存系统,主要用于加速动态Web应用。 3. **HBase**:基于Hadoop的分布式列式数据库,适用于大数据场景下的实时查询。 4. **Cassandra**:Facebook开发的分布式NoSQL数据库,适合大规模数据...

    cpp-SimDB一个高性能共享内存无锁跨平台单文件无依赖C11键值存储

    SimDB是一个专为C++开发的高性能键值存储系统,其设计目标是提供高效、安全且易于集成的数据存储解决方案。作为一个无锁的共享内存...对于C++和NoSQL数据库感兴趣的开发者来说,SimDB是一个值得研究和实践的项目。

Global site tag (gtag.js) - Google Analytics