一个极其轻量级的小巧的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可以打开。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值