实现一个小型数据库--记一次中级软件设计实作浮沉历程

article/2025/11/5 6:49:12

说在前头:本篇文章主要是记录这次项目的过程,不全是贴代码,具体的程序移步这里,不喜欢的同学请轻喷。

事件起因:大三狗一枚,专业是软件应用。这学期的中级软件设计实作题目是实现一个小型的数据库,具体的题目要求如下:
建立一个类似Oracle\SQL Server的小型数据库系统:

  • 可建立表,表有字段、类型
  • 表中可通过SQL语句填入数据(只能是特定类型)和查询数据;
  • 对主键字段,应自动建立索引;
  • 当进行查询时,在主键上应是基于索引的高效查询,而不能是字符串匹配这样的原始查询。

觉得题目似曾相识的同学,应该猜到我是哪所大学的了吧。一番Google、百度下来,最终确定了实现成一个Android的应用,毕竟这学期刚学的Android,这知识还滚烫着呢,而且Android的各种框架已经很成熟了,不用重复造轮子了。

前期准备:既然需求已经如此明确,接下来就是进行界面设计。然而自己并没有高大上的审美,也没有美术的基础,所以并不敢有太高的要求,但是业务逻辑要通顺,其他只能说长得不丑就行了。我用的是Mac系统下的一个Sketch的软件绘制的原型图,在这里就不贴出来了,具体的应用界面下面有。
接下来就是技术准备了,实现一个小型数据库,我总结了以下几点主要的技术难点:

  • 首先是主流数据库系统的实现原理;我主要参看了以下链接的内容:数据库的最简单实现、数据库索引的实现原理、为什么要用B+树结构——MySQL索引结构的实现等等技术博客,感谢各位无私奉献的大牛们~
  • 其次也是最难的部分是B+树,当前的很多数据库系统都是用B+树。关于B+树的总结,可以参看我的另一篇博客。
  • 最后就是Android的相关知识。这个需要长期的积累,遇到不会的我都会Google,或者查看技术博客,stackoverflow,github等等也有很多轮子可以直接用。

实际编码:终于来到真正的打大怪阶段了。这一部分内容我直接按界面(Activity)进行划分。

  • 主界面(Main Activity):首先是界面展示
    主界面1
    主界面2
    主界面上就是所有已经建好的表的列表,点击列表项则弹出对话框进行删除表、添加数据、查询数据操作,这三个操作具体实现在后面会详细说;其次右上角是新建表的按钮,点击跳转到对应的界面。主界面逻辑都很简单,值得一提的是刷新列表的操作我是放在onResume函数中,所以每次进入主界面就会刷新列表。代码片段如下:
@Override
protected void onResume()
{super.onResume();refreshSharedPreferencesList();  // 刷新列表
}
  • 新建表界面(AddTable Activity):界面展示如下:
    新建表界面展示
    界面上一个是编辑框输入字段名,一个是对应数据类型的下拉列表,填好一个字段信息后按右上角的”+”按钮再生成一对新的字段名框和类型列表,所有的编辑框和下拉列表保存在ArrayList中,且默认第一个是主键,最后按下面的确定按钮新建表。
    考虑到数据量小,而且是键值对应的形式,我将表的信息保存SharedPreference中,以用户输入的表名命名该文件。相关代码如下:
private List<EditText> editTextList = new ArrayList<>();
private List<Spinner> spinnerList = new ArrayList<>();// 将字段名和对应的类型存储到SharedPreferences中
private void saveInSharedPreferences(String tableName)
{SharedPreferences.Editor editor = getSharedPreferences(tableName, MODE_PRIVATE).edit();int index = -1;for (EditText editText : editTextList) {index++;String fieldName = editText.getText().toString();Spinner spinner = spinnerList.get(index);String type = spinner.getSelectedItem().toString();editor.putString(String.valueOf(index), fieldName+"&"+type);}editor.commit();
}

因为SharedPreference内部是用HashMap存储的,所以字段是无序的,为了取出的时候保持有序我只能将所以的键依次设为递增的整数,值通过’&’符号复合字段名和对应的类型,等取出的时候在解析出来。另外,刚刚主界面有删除表的操作,现在可以补上具体操作:找出SharedPreference存储的位置(haredPreferences 文件都是存放在/data/data/packagename/shared_prefs/目录下的),根据文件名删除对应的文件即可,代码如下:

// 删除表
private void deleteTableAction(String tableName)
{File prefsdir = new File(getApplicationInfo().dataDir,"shared_prefs");if(prefsdir.exists() && prefsdir.isDirectory()){String[] list = prefsdir.list();for (String fileNameWithEx : list) {String fileName = getFileNameNoEx(fileNameWithEx);if (fileName.equals(tableName)) {File deleteFile = new File(prefsdir, fileName+".xml");deleteFile.delete();refreshSharedPreferencesList(); //刷新列表}}}
}
  • 插入界面(ExecSQL Activity):国际惯例展示界面先:
    插入界面
    考虑到插入界面和搜索界面都是输入SQL语句然后执行操作,所以共用了同一个界面(ExecSQL Activity),下面不再说明。因为输入插入语句然后按”执行”按钮然后在当前界面并不能立刻进行查询操作,同时需要永久存储插入的数据,所以考虑将所有的插入语句存储到文件中,然后在需要执行查询的时候在取出插入语句插入到B+树上,然后进行查询。相关代码如下:
// 将插入语句写进文件中
private void writeInsertSqlToFile(String fileName)
{FileOutputStream out = null;BufferedWriter writer = null;try {out = openFileOutput(fileName, Context.MODE_APPEND);        // 追加模式writer = new BufferedWriter(new OutputStreamWriter(out));String insertSQLStatement = sqlEdit.getText().toString();String[] lines = insertSQLStatement.split(System.getProperty("line.separator"));    // 按行截取int length = lines.length;// 将所有的插入语句写入文件中for (int i = 2; i < length; i++) {String oneLine = lines[i];//Todo: 此处应该检查每一行数据的正确性writer.write(oneLine);writer.newLine();   // 换行Log.d("write oneLine", oneLine);}sqlEdit.setText(null);} catch (IOException e) {e.printStackTrace();} finally {try {if (writer != null) {writer.close();}} catch (IOException e) {e.printStackTrace();}}
}
  • 查询界面(ExecSQL Activity):界面展示如下:
    查询界面
    查询的时候先取出where语句,然后解析出查询的时候具体的限定条件,具体代码如下:
// 从表中查询数据
private void queryFromTable()
{BPlusTree tree = new BPlusTree(tableName, BPLUSTREE_DEGREE);String insertSql = readInsertSqlFromFile(tableName);// 将数据逐条插到B+树上if (insertDataInTree(tree, insertSql)) {String querySql = sqlEdit.getText().toString();String[] twoStr = analyseQuerySqlStatement(querySql);ArrayList<String> resultList = new ArrayList<String>();if (twoStr[0].equals(fieldNameArray.get(0))) {// 查询主键Object result = tree.search(twoStr[1]);if (result != null) {String resultString = formatResultMapToString((Map) result, twoStr[1]);resultList.add(resultString);}} else {// 查询其他属性Node head = tree.getHead();resultList = traverseTreeToSearch(head, twoStr);}}
}

取出查询结果存放到ArrayList中,跳转到查询结果界面并putExtra把查询结果传过去。

  • 查询结果界面(QueryResult Activity):最后就是展示查询的结果了:
    查询结果界面
    这里只需展示查询结果到列表中即可。

后记:当做完整个项目之后回头看看,似乎做了什么了不得的事,又似乎什么都没有做的样子。通过这次浮沉历程,我深刻体会到做好前期准备是多么的重要,一遍遍改数据结构、数据类型是很痛苦的……还有一点体会就是应该把model层(MVC框架)写的健壮,具有鲁棒性,得益于我花了4、5天的B+树,我后期的时候只管组织好界面等其他部分即可,不用担心我的B+树会闹别扭。看来设计模式果然灰常重要的,《大话设计模式》、《设计模式之禅》……你们等着我,我交完这次作业就过来找你们!!!
PS: 我将这次的完整程序放在了这里,这是初期版本,可能会有更新,下了初期版本想要更新版本的可以私信我。也欢迎各位大牛拍砖,你们的意见是我前进最好的指导,谢谢。


http://chatgpt.dhexx.cn/article/ocUpVHAp.shtml

相关文章

用xml充当小型数据库案例

利用dom4j工具&#xff0c;将user.xml作为一个小型的数据库&#xff0c;然后控制台输入进行用户名与密码的匹配 /*user.xml文件放在src下*/ <?xml version"1.0" encoding"utf-8"?> <users><user id"001" name"ecri" …

数据库上机3(小型数据库应用程序开发)

注&#xff1a; ①各上机报告均根据《数据库技术与应用》课程的上机任务所做。 ②课程教材为 《数据库系统概论&#xff08;第五版&#xff09;》/王珊, 萨师煊编著/北京:高等教育出版社,2014 上机要求&#xff1a; 1、自学上层应用访问数据库的方式&#xff08;如ODBC、ADO、…

【SQL数据库设计】数据库设计【小型数据库】

数据库设计 需求 表结构字段类型、是否允许为null、是否有默认值索引设计数据库引擎的选择 根据产品原型分析&#xff0c;词性分析法&#xff0c;名词创建表或字段&#xff0c;动词表示关系。 数据存储&#xff1a;长期存储的数据&#xff0c; 1.主键&#xff1a;唯一、自增。 …

小型数据库系统开发作业

文章目录 题目数据库设计UI界面开发展示 原文链接&#xff1a;https://zhanghan.xyz/posts/60088/ 题目 自学上层应用访问数据库的方式&#xff08;如ODBC、ADO、JDBC、MySQLi或者其它&#xff09;&#xff0c;根据您使用的上层语言&#xff08;不限语言&#xff08;但要求与自…

关于Freesurfer提取annotation分区结构特征的命令mri_segstats

Freesurfer提供了基于分区模板提取常规特征&#xff08;area, volume, thickness, thicknessstd, meancurv, gauscurv, foldind, curvind&#xff09;的指令mris_anatomical_statsaparcstats2table还有可以提取从fMRI或DWI产生的结果以及一些特殊的结构特征&#xff08;如LGI&a…

Linux下使用Freesurfer的两种方法

文章目录 1. 直接在终端使用准备工作开始运行 2. 通过调用python文件使用 1. 直接在终端使用 重点&#xff1a;Freesurfer安装完成后&#xff0c;需要在相同的用户名下运行&#xff0c;并且所有文件数据也要放在此用户下 放在其他地方可能会因为没有权限而运行失败 官网流程说…

freesurfer入门-试图理解freesurfer输出的数据

因为一些原因想要学习使用freesurfer,虽然照着tutorial跑了起来但是完全不知道跑出来的是个啥,所以准备弄一篇文章记录每个部分是干啥的,此文为记录 能记多少是多少吧… FreeSurfer内数据 labelmriorgtransforms scriptsstatssurf 首先要提一下比较常见的两个词:lh和rh 如果我没…

FreeSurfer入门(1) Output Data

目录 前言一、使用freeview查看卷二、使用freeview查看3D surfacePial surfacewhite surfaceInflated SurfaceThickness MapCortical Parcellation 前言 因一些原因需要学习FreeSurfer,然而教程比较少有些难懂,看了一段时间觉得可能要钻钻牛角尖才可以完成学习,所以开始记笔记…

IXI数据预处理 + Linux + freesurfer

目录 1. freesurfer下载安装测试1.1 下载受阻&#xff0c;安装axel-2.4,多线程下载1.2 安装1.3 安装时出现的问题1.4 测试1.5 使用前注意 2. freesurfer 处理IXI2.1 freesurfer 的使用2.2 从零开始处理IXI2.2.1 命令行skull_stripping 单个.nii文件2.2.2 分析处理完成后的文件2…

Freesurfer的简单使用和一些基础知识

Freesurfer Freesurfer是用于MRI图像处理和分析的一款开源软件&#xff0c;可进行多种模态数据的预处理&#xff0c;皮层重建&#xff0c;volume与surface的互相之间的配准等。 MRI成像 https://www.csdn.net/tags/Mtzagg1sNzM3MTMtYmxvZwO0O0OO0O0O.html MRI成像原理&…

FreeSurfer汉化教程

介绍FsFAST的预处理 根据官网的英文进行翻译&#xff0c;并在使用过程中所犯的错误进行解决的过程 介绍Tutorial Data 下载以及安装 安装 安装Tutorial Datasets 从教程数据&#xff0c;创建文件tutorial_data在自己的工作路径中。 curl https://surfer.nmr.mgh.harvard.e…

Freesurfer教程(ubuntu)

Freesurfer教程&#xff08;ubuntu&#xff09; 参考链接&#xff1a;http://www.wjhsh.net/zhhfan-p-13405572.html 1.安装 freesurfer的安装教程各个网站上都用详细的过程&#xff0c;这里不再叙述 这个命令是在处理tutorial_data中的dcm数据时使用的&#xff1a;recon-al…

freeSurfer颅骨剥离

命令参考 https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all recon-all -i 输入文件路径.nii -s 创建用于保存文件夹名称 -sd 保存文件夹所在的目录 -命令 -autorecon2-cp 输入输出参考 https://surfer.nmr.mgh.harvard.edu/fswiki/ReconAllDevTable orig/001.mgz 将…

freesurfer使用

一.做灰白质分割 我的目的是得到某被试的脑白质mask。 1.首先找了freesurfer教程&#xff0c;直接打开了freeview&#xff1b; 2.可视界面中没有直接的wmseg功能&#xff1b; 3.去使用freeview的手册查询wmseg&#xff08;开始怀疑这种操作不叫该名词..&#xff09;&#x…

【freesurfer学习1】freesurfer结构像批处理

freesurfer结构像批处理 最近0基础新入脑科学的坑&#xff0c;在等待申请数据集的时候&#xff0c;顺便学习一下freesurfer。 软件的安装稍后在评论区补上。 recon-all 分割重建 在我自定义的重建文件夹recon下有test文件夹&#xff0c;有两个文件夹demo1dcmnii&#xff0c;…

FreeSurfer和FSL的安装和使用(脑部图像去除头骨+对图像和label同时进行仿射对齐)教程

FreeSurfer当前只支持Linux系统和Mac OS。我所使用的系统是Ubuntu 16 .0.4&#xff0c;FreeSurfer的安装耗时较小&#xff0c;但是在处理时耗时较长&#xff0c;可能需要数个小时&#xff0c;甚至一天&#xff0c;这个取决于机器性能&#xff0c;但是和GPU好像没太大关系。下面…

FreeSurfer的安装及使用(个人踩坑记录)

一、环境要求 目前只支持在Linux和MacOS系统&#xff0c;虽然可以用 -parallel 进行多线程处理&#xff0c;但基本消耗的是CPU内存。 二、FreeSurfer的下载与安装 1. 下载安装包 官网链接&#xff1a;rel7downloads - Free Surfer Wiki 根据自己系统型号下载对应安装包&am…

【数学建模】统计回归模型

一、 多元线性回归 matlab统计工具箱 [b,bint,rint,stats]regress(y,x,alpha) 输入 y~n维数据向量数据矩阵&#xff0c;第1列为全1向量alpha(置信水平,0.05) 输出 b~β的估计值bint~b的置信区间r~残差向量y-xbrint~r的置信区间&#xff08;置信区间包含0则对y的影响不太显…

统计学习模型——决策树

决策树学习的三个步骤&#xff1a;特征选择、决策树的生成和决策树的修剪 一、决策树模型&#xff08;分类与回归方法&#xff09; 1.1 基本概念 决策树可为多叉树&#xff0c;是描述对实例进行分类的树形结构决策树由结点和有向边组成。其中结点又分为&#xff1a;内部结点…

机器学习的概率统计模型(附代码)(一)

目录 概率论 1.1 离散随机变量分布 1&#xff09;伯努利分布 2&#xff09;二项分布 3&#xff09;泊松分布 1.2 连续随机变量分布 1&#xff09;均匀分布 2&#xff09;指数分布 3&#xff09;正态分布 总结 系列文章目录 概率论 概率论&#xff0c;是研究随机现象数量规…