新写的一个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. **SimpleDBM**: 这是一个轻量级的键值存储库,适用于简单的本地数据存储需求。它提供了一种简单的方式来保存和检索数据,而无需复杂的数据库管理系统。 2. **Redis**: 虽然Redis本身是一个服务器端的键值存储...
2. **Key-Value存储**:这种数据结构简单直观,适合快速查找和存储,常见于缓存和轻量级数据库中。 3. **持久化**:指数据不仅存储在内存中,还会定期或在每次写入时写入磁盘,即使系统崩溃也能恢复数据。 4. **高...
这个数据库系统被设计成轻量级且高效,它借鉴了其他知名的键值存储解决方案,如Berkeley DB、LevelDB和SQLite4的LSM(Log-Structured Merge Tree)数据结构。tkvdb的核心目标是提供一种简单而快速的方式来存储和检索...
SHDB利用Python的强大功能,为Shell脚本提供了轻量级的数据存储解决方案,适用于那些需要简单数据管理但又不想引入大型数据库系统的场景。 **核心特性** 1. **易用性**:SHDB的API设计简洁,易于理解和使用,使得...
Kyoto Cabinet是一个轻量级的键值数据库;Voldemort是一种分散式键值存储系统;Redis除了作为键值存储系统外,还提供了丰富的数据类型如列表(list)、集合(set)、有序集合(sorted set)等。 总之,NoSQL数据...
3. **SQLite**:是一个轻量级的嵌入式SQL数据库,广泛应用于移动设备和桌面应用。 4. **LevelDB**:是Google开发的一个简单的键值对存储库,是`RocksDB` 的基础。 5. **Crates**:是Rust的包管理器和构建工具,帮助...
它被设计为轻量级的解决方案,适用于那些需要快速数据存储和检索的应用场景,尤其适合在资源受限的环境中运行。Sophia的特性使其在NoSQL数据库领域中脱颖而出,下面将详细探讨其关键知识点。 1. **键值存储模型** ...
蜂巢(Hive)是一个基于Dart语言的轻量级、高性能的键值数据库系统,专为现代应用程序设计。在本文中,我们将深入探讨蜂巢的核心特性、如何使用它、其与Dart和Flutter的关系,以及它在NoSQL数据存储中的作用。 1. *...
NoSQL的历史可以追溯到1998年,由Carlo Strozzi开发的轻量级数据库系统首次使用这个术语。然而,真正引起广泛讨论和应用是在2009年,随着Last.fm的Johan Oskarsson和Rackspace的Eric Evans提出非关系型、分布式和无...
它具有以下特点:轻量级. 无守护进程,无需任何额外的安装和配置,你只需要import jsonDb即可使用,非常方便.NOSQL. 类似于mongoDb的非关系型数据库.内存数据库. 所有数据基于内存进行操作和访问,性能相对较高.目前版本...
>1、轻量级. 无守护进程,无需任何额外的安装和配置,你只需要import jsonDb即可使用,非常方便. >2、NOSQL. 类似于mongoDb的非关系型数据库. >3、内存数据库. 所有数据基于内存进行操作和访问,性能相对较高.目前...
FlyDB是一个用C语言编写的轻量级键值(Key-Value)存储系统,它为开发者提供了一种高效、简单的方式来存储和检索数据。作为NoSQL数据库的一种,FlyDB不遵循传统的表格型数据库结构,而是采用键值对的形式,这使得它...
:owl: owlcache是Go编写的轻量级,高性能,非集中式,分布式键/值内存缓存数据共享应用程序(在某些情况下用作轻量级数据库)。您可以将每个节点视为单独的键/值数据您可以通过集群查询任何节点的数据,以获取...
RLite是一个小巧而强大的数据库引擎,它完全兼容Redis命令,并且具有无服务器、零配置的特点,这意味着它不需要专门的服务器进程来运行,而是可以直接在本地文件系统上作为嵌入式数据库使用。这种设计使得RLite成为...
CannonDB是为人类设计的轻量级但功能强大的键值数据库。 安装 pip安装cannondb 产品特点 由磁盘B树维护,因此插入/获取/删除足够快。 支持键/值的str/int/float/dict/list/UUID类型。 将数据存储在默认文件中,但...
2. **Memcached**:轻量级缓存系统,主要用于加速动态Web应用。 3. **HBase**:基于Hadoop的分布式列式数据库,适用于大数据场景下的实时查询。 4. **Cassandra**:Facebook开发的分布式NoSQL数据库,适合大规模数据...
SimDB是一个专为C++开发的高性能键值存储系统,其设计目标是提供高效、安全且易于集成的数据存储解决方案。作为一个无锁的共享内存...对于C++和NoSQL数据库感兴趣的开发者来说,SimDB是一个值得研究和实践的项目。