一个极度轻量级的小巧的Key/Value数据库(NOSQL)
一个极其轻量级的小巧的Key/Value数据库(NOSQL)
新写的一个Java Key/Value数据库,有些NOSQL的意思,呵呵。跟大家共享出来,小弟是个新手,请不要拍的太厉害,谢谢!
程序比较轻量级,非常的小巧,只有一个Java类文件。在实用中对于比较简单的数据结构,用起来还是比较方便的,性能也好。
使用的时候有个前提,那就是要有Servlet容器(引擎)即可。类代码如下:
同时写了用于两个页面测试和管理的JSP文件,admin.jsp代码如下:
admin2.jsp代码如下:
附件里是源代码,直接用netbeans可以打开。
新写的一个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可以打开。