- 浏览: 103776 次
- 性别:
- 来自: 杭州
最新评论
-
whatlonelytear:
赞
java注解应用实例 - Annotation, 自定义注解, 注解类规则 -
砚台观月:
你好,例子还有吗,我想要份学习看下。提供的链接找不到了。
java网络编程之Http多线程下载应用实例 -
xianghanscce:
...
java泛型应用实例 - 自定义泛型类,方法 -
yhx1231:
...
Java反射应用实例 -
beiyeren:
写的不错啊
java注解应用实例 - Annotation, 自定义注解, 注解类规则
注: 转载请注明出处: http://hejiangtao.iteye.com , 用于商业得给我分成
这个是一个文本数据库简单的实现思路 , 从这里 可以下载到完整的java代码工程: http://download.csdn.net/detail/hejiangtao/3991735
什么人适合阅读本文:
1. 我自己平时写些小程序,存储数据使用那些收钱/开源的数据库太浪费电脑资源,直接存到文件里面更方便. 所以才搞了这个东东, 如果你和我有同样的苦恼和需求,你可以参考下,看有木有你需要的. 我简单把实现思路写了一下,需要的兄弟也可以参考下,根据情况自己做扩展或者封装 .
2.其中使用到了java泛型,java反射机制,文本输入输出等技术,如果想研究这些技术也可以参考这些代码,,看有么有你需要的.
设计思路说明:
1.数据存相关规则
一 般的数据库的存储规则是不暴露给用户的,如果使用文本来存储数据,用户可以随便修改,所以必须建立一定的规则,用户不能随意手动修改文本数据库内容. 我实现的时候是一个表,一个文本文件; 一个表对应一个Bean class, 并假设,Bean Class的名字就是文件名加Bean后缀, 列名和TableBean的域(Field)名是一样,这样可以轻松使用java反射机制; 文本文件的第一行有效列需指明列名和顺序,因为Field的顺序是不可控的,存在文本里面就可控了; 第一列为主键,列与列之间使用$_$分割.
2. 关键算法/设计
1)读写文件--数据肯定是多行的,所以使用buffered reader 和writer是必要的, 写入和读出数据的时候都按照一条记录一行的方式,方便解析
2) 文本数据和Bean之间的转化--将数据存入Bean是为了更方便的解析和使用, 由于Bean的Class Name和Field Name及其Set/Get方法都是采用同样的命名方式,所以可以通过使用一个java泛型方法实现所有表/Bean的文本数据和Bean之间的转化,访 问数据也可以java反射机制访问.
3)数据分析--由于文件内容分析只能在内存里面分析,如果数据量太大,只能先一部分一本的分析,将分析完的数据先写入到临时文件, 本例作为demo就按照全部写入内存方式来分析
实现:
整个工程的文件分布如下如图:
1.在工程主目录下的db下面是两个示例表的文件T_FamilyMember.db, T_Home.db, 后缀名是.db其实是文本
2.在包名com.ross.filedb下面, tablebean下是两张表对应的Bean,命名必须符合规则; util下是一些公共的业务不相关的一些操作实现或系统级变量; FileDBTool.java则实现了基本的增/删/改/查功能.
3. junit.ross.filedb下是简单的junit功能测试用例 (木有main,看运行结果请用junit看 )
先把Bean和db文件贴出来,命名是相互对应的,很明显,就不浪费口舌了:
T_Home.db:
T_FamilyMember.db:[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$phone$_$email$_$address
- #Content Start
T_HomeBean.java:[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$gender$_$mobile$_$email$_$address$_$family_id
- #content start
T_FamilyMemberBean.java:[java] view plain copy
- package com.ross.filedb.tablebean;
- /**
- * Author: Jiangtao He
- * Since: MyJavaExpert v1.0
- */
- public class T_HomeBean
- {
- private String id;
- private String name;
- private String phone;
- private String email;
- private String address;
- //省略了set/get方法
- }
[java] view plain copy
- package com.ross.filedb.tablebean;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Since: MyJavaExpert v1.0
- */
- public class T_FamilyMemberBean
- {
- private String id;
- private String name;
- private String gender;
- private String mobile;
- private String email;
- private String address;
- private String family_id;
- //省略了set/get方法
- }
再介绍下我的通用方法和系统级变量:
SysValues.java:
系统及变量,主要是在使用java反射机制的时候分析类名或者文件名.
ResultBean.java:[java] view plain copy
- package com.ross.filedb.util;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Date: 2011-12-30
- * Version: MyJavaExpert v1.0
- * Description: system level variables
- */
- public class SysValues
- {
- // DB constant variables
- public static final String DB_Path = System.getProperty( "user.dir" )
- + System.getProperty("file.separator" ) + "db"
- + System.getProperty("file.separator" );
- public static final String DB_Bean_Suffix = "Bean" ;
- public static final String DB_File_Suffix = ".db" ;
- }
用于一般的方法返回结果.
FileProcess.java[java] view plain copy
- package com.ross.filedb.util;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Date: 2011-12-31
- * Since: MyJavaExpert v1.0
- * Description: To store the return value.
- */
- public class ResultBean
- {
- boolean result;
- String description;
- //省略了set/get方法
- }
java IO的操作,总要一堆的对象相互嵌套才能生成合适的writer或者reader, 这个类的作用就是把这个步骤汇总,其他类可以直接引用,省去这些繁琐的麻烦. 具体功能,代码里有详细注释.
[java] view plain copy
- package com.ross.filedb.util;
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.FileReader;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.PrintWriter;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Since: MyJavaExpert v1.0
- * Description: this class will implement the common file process.
- */
- public class FileProcess
- {
- /**
- * Description: get a buffered file append writer according the file name (with full path)
- * PrintWriter will be more easy to access text, BufferedWriter is used to
- * cache the data to improve the performance.
- */
- public PrintWriter getAppendBufferedFilePrintWriter(String sFullFileName)
- throws IOException
- {
- PrintWriter oPWriter = new PrintWriter( new BufferedWriter(
- new FileWriter(sFullFileName, true )));
- return oPWriter;
- }
- /**
- * Author: Jiangtao He
- * Description: get a buffered file writer according the file name (with full path)
- * PrintWriter will be more easy to access text, BufferedWriter is used to
- * cache the data to improve the performance.
- */
- public PrintWriter getBufferedFilePrintWriter(String sFullFileName)
- throws IOException
- {
- PrintWriter oPWriter = new PrintWriter( new BufferedWriter(
- new FileWriter(sFullFileName)));
- return oPWriter;
- }
- /**
- * Author: Jiangtao He
- * Description: get a buffered file reader according the file name (with full path)
- * BufferedReader is used to cache the data to improve the performance.
- */
- public BufferedReader getBufferedFileReader(String sFullFileName)
- throws IOException
- {
- BufferedReader oBufferedReader = new BufferedReader( new FileReader(
- sFullFileName));
- return oBufferedReader;
- }
- }
最后就是我们的增删改查功能实现了:
FileDBTool.java:
1. 看下如何根据bean类获取对应的文本数据库的表文件名.
a.首先获取完整类名,例如 com.ross.filedb.tablebean.T_HomeBean;
b.然后去除包名,只剩T_HomeBean;
c.再将Bean后缀去掉,加上路径和.db后缀,就将文本数据库的表文件名给拼出来了.
2. 看下如何将Bean转换成一条表记录(使用"$_$"分割各列,各列需按照指定顺序排列)[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: Get the text DB's file name with full path name.
- * assume that all the bean class of table is formed by
- * table name + suffix (like: Bean), for example: T_Home-->T_HomeBean.java
- * @param oT: the object of bean
- * @return sFullFileName: db file name with completing path
- */
- private <T> String getFullTableFileName(T oT)
- {
- String sFullFileName = "" ;
- // the class name is like com.ross.filedb.tablebean.T_HomeBean, only keep
- // T_Home
- String[] sTmps = oT.getClass().getName().split("\\." );
- sFullFileName = sTmps[sTmps.length - 1 ];
- sFullFileName = SysValues.DB_Path
- + sFullFileName.substring(0 , sFullFileName
- .indexOf(SysValues.DB_Bean_Suffix))
- + SysValues.DB_File_Suffix;
- return sFullFileName;
- }
a.首先根据上面的方法拼出来的带路径的文件名读出列名和各列顺序
b.然后根据列名拼出类的Field的get方法
c.再根据拼接出来的get方法,使用java的反射机制, 生成对应的Method对象, 并使用invoke方法执行该方法
d.使用循环拼接各个Field的值在一起,并使用"$_$"分割各个Field
另外,为了使所有的Bean都可以通过这一个方法转换成对应的字符串,将方法定义成了泛型方法, 可以看到泛型T.
不了解java反射和泛型的可以从网上搜一下,或者看我后续的博客了解
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description:
- * 1. Get the string of new record which will be save to DB
- * 2. Since the object is a generic object, so the reflect mechanism will be
- * used to access the data of the bean.
- * 3. assume that all fields'nameof the bean class is the same as
- * the columns' name of table. The first available line should
- * give the columns' sequence, which is start with 'ColumnSeq'.
- * for different columns, they will be separated by '$_$'
- * @param oT: the object of bean
- * @param sFullFileName: DB file name with completing path
- * @return sRowData: return the new record string
- * @throws IOException
- * @throws NoSuchMethodException
- * @throws SecurityException
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- */
- private <T> String convertBeantoStr(T oT, String sFullFileName)
- throws IOException, SecurityException, NoSuchMethodException,
- IllegalArgumentException, IllegalAccessException,
- InvocationTargetException
- {
- // define the return value
- String sRowdata = "" ;
- String[] sColumns = null ;
- BufferedReader oBRead = null ;
- // to get the columns' sequence
- try
- {
- oBRead = fileProcess.getBufferedFileReader(sFullFileName);
- String sReadLine;
- while ( null != (sReadLine = oBRead.readLine()))
- {
- sReadLine = sReadLine.trim();
- // skip the comments and empty lines
- if ( "" .equals(sReadLine) || sReadLine.startsWith( "#" ))
- {
- continue ;
- }
- // find the columns' sequence
- if (sReadLine.startsWith( "ColumnSeq" ))
- {
- sColumns = sReadLine.split(":" )[ 1 ].split( "\\$_\\$" );
- break ;
- }
- }
- }
- catch (IOException e)
- {
- // print e, and throw it, so the method which invoked it can process
- // it freely.
- e.printStackTrace();
- throw e;
- }
- finally
- {
- // close the writer
- if ( null != oBRead)
- {
- oBRead.close();
- }
- }
- // define field variable
- Method oMethod = null ;
- String sFieldName = "" ;
- String sMethodName = "" ;
- // get the corresponding columns' value through the reflect mechanism
- for ( int i = 0 ; i < sColumns.length; i++)
- {
- // initialize the method name
- sMethodName = "get" ;
- // get the get method name of the current column
- sFieldName = sColumns[i].trim();
- if (sFieldName.length() > 1 )
- {
- sMethodName = sMethodName
- + sFieldName.substring(0 , 1 ).toUpperCase()
- + sFieldName.substring(1 );
- }
- else
- {
- sMethodName = sMethodName + sFieldName.toUpperCase();
- }
- // get the get method
- oMethod = oT.getClass().getMethod(sMethodName);
- // Execute the method to get the value of the current field
- // add the separator of the columns too
- sRowdata = sRowdata + oMethod.invoke(oT) + "$_$" ;
- }
- // remove the last separator
- if (! "" .equals(sRowdata))
- {
- sRowdata = sRowdata.substring(0 , sRowdata.lastIndexOf( "$_$" ));
- }
- return sRowdata;
- }
3.有了上面两个步骤,就可以实现数据库记录的插入功能了a. 这个insert方法的传入参数就是一个Table Bean的对象, 当然对象里面有你要存储到文本文件里的数据
b.根据这个Table Bean的对象获取带路径的完整文件名
c.将Bean转化成一条合格的字符串
d.将该字符串写入对应的DB文件的最后(为了保证数据在单独的一行,数据前先插入了换行符)
同样的,为了使所有的表Bean都可以通过这一个方法插入数据,将方法定义成了泛型方法.
本方法并没有实现检查主键的工作,自己可以根据需要重载或封装实现.
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: Insert one record to text DB
- * @param oT: the object of bean
- * @return oResult:
- * ResultBean.result: true - insert success; false - insert failed
- * ResultBean.description: the description of the result;
- * @throws IOException
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws NoSuchMethodException
- * @throws IllegalArgumentException
- * @throws SecurityException
- */
- public <T> ResultBean insert(T oT) throws IOException, SecurityException,
- IllegalArgumentException, NoSuchMethodException,
- IllegalAccessException, InvocationTargetException
- {
- ResultBean oResult = new ResultBean();
- boolean bRet = false ;
- String sDescription = "" ;
- // get full text DB file name with full path
- String sFullFileName = this .getFullTableFileName(oT);
- // get sRowdata
- String sRowData = this .convertBeantoStr(oT, sFullFileName);
- PrintWriter oPWriter = null ;
- try
- {
- // get writer
- oPWriter = fileProcess
- .getAppendBufferedFilePrintWriter(sFullFileName);
- // write to file
- oPWriter.write(System.getProperty("line.separator" ) + sRowData);
- oPWriter.flush();
- // set return value as success
- bRet = true ;
- sDescription = "the insert record is \"" + sRowData + "\". "
- + ". It is saved in \"" + sFullFileName
- + "\" successfully." ;
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw e;
- }
- finally
- {
- // close the writer
- if ( null != oPWriter)
- {
- oPWriter.close();
- }
- }
- // set final result.
- oResult.setDescription(sDescription);
- oResult.setResult(bRet);
- return oResult;
- }
4. 先了解下如何将一条记录从文本数据库表文件中删除
java 没有删除文本中某一行的接口,所以实现删除的算法就是,将文本内容全部读出来,将改行从缓存中删除,然后将处理后的缓存数据覆盖写入原文件. 缓存方式有两种一种全部存入内存适用于数据较少的时候,另一种是写入临时文件,适用于大数量时候.本demo全部读入内存了.
a. 获取对应DB文件的reader
b. 然后一行一行的读取,一行一行的判断是否当前行就是要删除的行,如果不是则加入缓存的字符串中,否则丢弃
c.将处理后的缓存字符串写入对应的DB文件
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description:
- * 1.delete the record from text DB file.
- * 2.the arithmetic is read all the contents in a string buffer except
- * the deleting record, then write to file again.
- * 3.One suggestion for huge data, develop your own method by using a temporary file
- * as a buffered
- * @param sRowData: the record which will be deleted from the file
- * @param sFullFileName: DB file name with completing path
- * @return bRet: true - insert success; false - insert failed
- * @throws IOException
- */
- private boolean deleteRecordFromFile(String sRowData, String sFullFileName)
- throws IOException
- {
- boolean bRet = false ;
- StringBuffer sbFinalContent = new StringBuffer();
- PrintWriter oPWriter = null ;
- BufferedReader oBRead = null ;
- // to get the columns' sequence
- try
- {
- oBRead = fileProcess.getBufferedFileReader(sFullFileName);
- String sReadLine;
- String sLastLIne = "sLastLIne" ;
- while ( null != (sReadLine = oBRead.readLine()))
- {
- sReadLine = sReadLine.trim();
- // make conjoined duplicated lines to one line
- // to avoid too many empty lines
- if (sLastLIne.equals(sReadLine))
- {
- continue ;
- }
- // delete the target record
- if (sRowData.equals(sReadLine))
- {
- // set result
- bRet = true ;
- continue ;
- }
- // cache in the buffer
- sbFinalContent.append(sReadLine).append(
- System.getProperty("line.separator" ));
- // set last line
- sLastLIne = sReadLine;
- }
- // get writer
- oPWriter = fileProcess
- .getBufferedFilePrintWriter(sFullFileName);
- // write the final content to file
- oPWriter.write(sbFinalContent.toString());
- oPWriter.flush();
- }
- catch (IOException e)
- {
- // print e, and throw it, so the method which invoked it can process
- // it freely.
- e.printStackTrace();
- throw e;
- }
- finally
- {
- if ( null != oBRead)
- {
- oBRead.close();
- }
- // close the writer
- if ( null != oPWriter)
- {
- oPWriter.close();
- }
- }
- return bRet;
- }
5. 有了上面的方法,我们就可以实现数据的删除功能了.
我们平时用的数据库可以使用主键或者其他字段作为条件来做删除, 这个在java里面就是多了一步字符串的分析操作.所以我没有实现这个功能, 在本demo中就是直接将整条记录作为判断条件来删除数据, 可以根据实际需要扩展本方法.
a.首先根据表的Bean对象获取文件名
b.然后将Bean对象转换为合格的表记录字符串
同样的, 为了使所有的表Bean都可以通过这一个方法删除数据,将方法定义成了泛型方法.c.调用上面的方法将记录从文件中删除.
6.再看下如何更新文本数据库中的一条记录[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: Delete one record from text DB
- * @param oT: the object of bean
- * @return oResult:
- * ResultBean.result: true - insert success; false - insert failed
- * ResultBean.description: the description of the result;
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws NoSuchMethodException
- * @throws IOException
- * @throws IllegalArgumentException
- * @throws SecurityException
- */
- public <T> ResultBean delete(T oT) throws SecurityException,
- IllegalArgumentException, IOException, NoSuchMethodException,
- IllegalAccessException, InvocationTargetException
- {
- ResultBean oResult = new ResultBean();
- boolean bRet = false ;
- String sDescription = "" ;
- // get full text DB file name with full path
- String sFullFileName = this .getFullTableFileName(oT);
- // get sRowdata
- String sRowData = this .convertBeantoStr(oT, sFullFileName);
- // delete from file
- bRet = this .deleteRecordFromFile(sRowData, sFullFileName);
- // set result description
- if (bRet)
- {
- sDescription = "The deleted record is \"" + sRowData + "\" . "
- + "It is delete from \"" + sFullFileName
- + "\" successfully." ;
- }
- else
- {
- sDescription = "The deleting record \"" + sRowData
- + "\" is not there in the file" + " \"" + sFullFileName
- + "\"." ;
- }
- // set final result.
- oResult.setDescription(sDescription);
- oResult.setResult(bRet);
- return oResult;
- }
更新记录算法和删除记录是一样的,只不过删除时丢弃该记录, 更新时更换该记录, 不再赘述.
a. 获取对应DB文件的reader
b. 然后一行一行的读取,一行一行的判断是否当前行就是要删除的行,如果不是则加入缓存的字符串中,否则增更换为目标字符串
c.将处理后的缓存字符串写入对应的DB文件
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description:
- * 1.update the record to text DB file.
- * 2.the arithmetic is read all the contents in a string buffer, replace
- * the updating record, then write to file again.
- * 3.One suggestion for huge data, develop your own method by using a temporary file
- * as a buffered
- * @param sRowData: the record which will be deleted from the file
- * @param sFullFileName: DB file name with completing path
- * @param sPrimaryKeyValue: the value of the primary key
- * @return bRet: true - insert success; false - insert failed
- * @throws IOException
- */
- private boolean updateRecordToFile(String sRowData,
- String sPrimaryKeyValue, String sFullFileName) throws IOException
- {
- boolean bRet = false ;
- StringBuffer sbFinalContent = new StringBuffer();
- PrintWriter oPWriter = null ;
- BufferedReader oBRead = null ;
- try
- {
- oBRead = fileProcess.getBufferedFileReader(sFullFileName);
- String sReadLine;
- String sLastLIne = "sLastLIne" ;
- String[] sColumnValues = null ;
- while ( null != (sReadLine = oBRead.readLine()))
- {
- sReadLine = sReadLine.trim();
- // make conjoined duplicated lines to one line
- // to avoid too many empty lines
- if (sLastLIne.equals(sReadLine))
- {
- continue ;
- }
- // handle the comments, empty line, ColumnSeq line
- if (sReadLine.startsWith( "#" ) || "" .equals(sReadLine)
- || sReadLine.startsWith("ColumnSeq" ))
- {
- // cache in the buffer
- sbFinalContent.append(sReadLine).append(
- System.getProperty("line.separator" ));
- continue ;
- }
- // handle changing record
- sColumnValues = sReadLine.split("\\$_\\$" );
- if (sPrimaryKeyValue.trim().equals(sColumnValues[ 0 ].trim()))
- {
- // cache in the buffer
- sbFinalContent.append(sRowData).append(
- System.getProperty("line.separator" ));
- continue ;
- }
- // cache normal record in the buffer
- sbFinalContent.append(sReadLine).append(
- System.getProperty("line.separator" ));
- // set last line
- sLastLIne = sReadLine;
- }
- // get writer
- oPWriter = fileProcess.getBufferedFilePrintWriter(sFullFileName);
- // write the final content to file
- oPWriter.write(sbFinalContent.toString());
- oPWriter.flush();
- // set result
- bRet = true ;
- }
- catch (IOException e)
- {
- // print e, and throw it, so the method which invoked it can process
- // it freely.
- e.printStackTrace();
- throw e;
- }
- finally
- {
- if ( null != oBRead)
- {
- oBRead.close();
- }
- // close the writer
- if ( null != oPWriter)
- {
- oPWriter.close();
- }
- }
- return bRet;
- }
7. 通过上面的更新方法,就可以实现记录的更新功能了.
同样的对与更新方法没有实现根据列值判断来更新相关的记录, 只是实现了根据主键更新整列数据局, 可以根据需要重写/扩展该方法
a.首先根据Table Bean后去带路径的玩这个路径名
b.在将Table Bean转换成一个合格的数据记录字符串
c.调用上面的方法,根据主键将目标记录替换
同样的, 为了使所有的表Bean都可以通过这一个方更新数据,将方法定义成了泛型方法.
8. 了解下如何根据列名获取Table Bean的get 方法[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: update one record from text DB
- * @param oT: the object of bean
- * @param sPrimaryKeyValue: the value of the primary key
- * @return oResult:
- * ResultBean.result: true - insert success; false - insert failed
- * ResultBean.description: the description of the result;
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws NoSuchMethodException
- * @throws IOException
- * @throws IllegalArgumentException
- * @throws SecurityException
- */
- public <T> ResultBean update(T oT, String sPrimaryKeyValue)
- throws SecurityException, IllegalArgumentException, IOException,
- NoSuchMethodException, IllegalAccessException,
- InvocationTargetException
- {
- ResultBean oResult = new ResultBean();
- boolean bRet = false ;
- String sDescription = "" ;
- // get full text DB file name with full path
- String sFullFileName = this .getFullTableFileName(oT);
- // get sRowdata
- String sRowData = this .convertBeantoStr(oT, sFullFileName);
- // delete from file
- bRet = this .updateRecordToFile(sRowData, sPrimaryKeyValue,
- sFullFileName);
- // set result description
- if (bRet)
- {
- sDescription = "The updated record is \"" + sRowData + "\". "
- + " It is update to \"" + sFullFileName
- + "\" successfully." ;
- }
- else
- {
- sDescription = "The updating record \"" + sRowData
- + "\" is not there in the file" + " \"" + sFullFileName
- + "\"." ;
- }
- // set final result.
- oResult.setDescription(sDescription);
- oResult.setResult(bRet);
- return oResult;
- }
由于列名和Bean的Field名字是一样的,根据这儿特性,可以拼接出来对应的set方法的方法名. 详细步骤可以参考注释
同样的, 为了使所有的表Bean都可以通过这一个方法获取set方法,将方法定义成了泛型方法.
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: Get all set method names.
- * assume that all the field names of bean class of table are the same as the column names
- * @param oT: the object of bean
- * @param sColumns: the columns
- * @return HashMap <String,String>
- * - key: column name;
- * - value: the corresponding set method name
- */
- private <T> HashMap<String, String> getSetMethods(String[] sColumns, T oT)
- {
- HashMap<String, String> oHM = new HashMap<String, String>();
- String sMethodName = "" ;
- String sFieldName = "" ;
- for ( int i = 0 ; i < sColumns.length; i++)
- {
- // initialize the method name
- sMethodName = "set" ;
- // get the get method name of the current column
- sFieldName = sColumns[i].trim();
- if (sFieldName.length() > 1 )
- {
- sMethodName = sMethodName
- + sFieldName.substring(0 , 1 ).toUpperCase()
- + sFieldName.substring(1 );
- }
- else
- {
- sMethodName = sMethodName + sFieldName.toUpperCase();
- }
- oHM.put(sColumns[i], sMethodName);
- }
- return oHM;
- }
9. 有了上面的方法,我们也可以更加easy的实现数据的查询功能了.
为了免去分析字符串的麻烦,本demo只是先了查询所有数据的功能,可以根据需要扩展该方法.
这个方法设计是将所有数据读取出来放入Bean中,一条记录就是一个Bean对象,所以最终返回值是一个Bean对象的list
a.首先获取对应的带路径的完整文件名
b.获取对应数据库文件的reader
c.将数据一条一条的读出来,一条一条的处理. 跳过注释,空行,及标示列名和列顺序的行, 将其他有效的数据库记录进行处理
d.根据列名得出所有field的set方法
c.将数据库记录分割后,调用set方法赋给Bean对象
d.将赋值完后的Bean对象加入List, 如此循环处理所有记录.
同样的,为了使所有的表Bean都可以通过这一个方法获取对应的数据列表,将方法定义成了泛型方法.
另外注意一点, 由于set方法是有输入参数的,所以使用反射机制构造或者执行方法的时候是需要指定这些参数类型或者参数的, 由于demo中的数据类型都是使用的String类型,所以是取巧了的, 如果需要支持其他类型,可以对此方法做修改,对类型做下分析.
[java] view plain copy
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Description: query all the records from text DB
- * @param oT: the object of bean
- * @param sPrimaryKeyValue: the value of the primary key
- * @return oTList: the object list of the bean
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- * @throws NoSuchMethodException
- * @throws SecurityException
- * @throws InstantiationException
- * @throws IOException
- */
- public <T> List<T> queryAll(T oT) throws IllegalArgumentException,
- IllegalAccessException, InvocationTargetException,
- SecurityException, NoSuchMethodException, InstantiationException, IOException
- {
- List<T> oTList = new ArrayList<T>();
- // get full text DB file name with full path
- String sFullFileName = this .getFullTableFileName(oT);
- BufferedReader oBRead = null ;
- try
- {
- oBRead = fileProcess.getBufferedFileReader(sFullFileName);
- String sReadLine;
- String[] sColumns = null ;
- HashMap<String, String> oHM = null ;
- String[] sColumnValues = null ;
- int iNumOfColumns;
- Method oMethod;
- while ( null != (sReadLine = oBRead.readLine()))
- {
- sReadLine = sReadLine.trim();
- // skip comments, empty line
- if (sReadLine.startsWith( "#" ) || "" .equals(sReadLine))
- {
- continue ;
- }
- // get set method names of the bean
- if (sReadLine.startsWith( "ColumnSeq" ))
- {
- sColumns = sReadLine.split(":" )[ 1 ].split( "\\$_\\$" );
- oHM = this .getSetMethods(sColumns, oT);
- continue ;
- }
- // get values of the a record
- sColumnValues = sReadLine.split("\\$_\\$" );
- // check the number of values is less than columns or not, the
- // smaller one will be used in the loop to avoid out of array
- // index exception
- iNumOfColumns = sColumnValues.length > sColumns.length ? sColumns.length
- : sColumnValues.length;
- for ( int i = 0 ; i < iNumOfColumns; i++)
- {
- // get the get method
- oMethod = oT.getClass().getMethod(oHM.get(sColumns[i]),String.class );
- // execute the method to set the value into bean
- oMethod.invoke(oT, sColumnValues[i]);
- }
- //add the bean into the bean list
- oTList.add(oT);
- //assign a new instance to the bean
- oT = (T) oT.getClass().newInstance();
- }
- }
- catch (IOException e)
- {
- // print e, and throw it, so the method which invoked it can process
- // it freely.
- e.printStackTrace();
- throw e;
- }
- finally
- {
- if ( null != oBRead)
- {
- oBRead.close();
- }
- }
- return oTList;
- }
至此增删改查功能的思路算是实现了.
我们使用junit做下测试看下效果--我在4个测试方法上都打了断点, 分别看下实际效果(由于junit代码较长,我就不贴了,感兴趣的可以下载下来看):
增加一条记录到home和member表:
控制台:
[java] view plain copy
- Insert one home record - result: true ; description: the insert record is "Ross_1$_$Ross's Home$_$252363693$_$ross.jiangtao.he@gmail.com$_$China P.R." . . It is saved in "E:\myspace\MyJavaExpert V1.0\db\T_Home.db" successfully.
- Insert one faminily member record - result: true ; description: the insert record is "Yan$_$Pery$_$Female$_$252363693$_$ross.jiangtao.he@gmail.com$_$null$_$Ross_1" . . It is saved in "E:\myspace\MyJavaExpert V1.0\db\T_FamilyMember.db" successfully.
数据库文件内容:T_Home.db:
T_FamilyMember.db:[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$phone$_$email$_$address
- #Content Start
- Ross_1$_$Ross's Home$_$252363693 $_$ross.jiangtao.he @gmail .com$_$China P.R.
[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$gender$_$mobile$_$email$_$address$_$family_id
- #content start
- Yan$_$Pery$_$Female$_$252363693 $_$ross.jiangtao.he @gmail .com$_$ null $_$Ross_1
查询home和member表的记录:
控制台:
[java] view plain copy
- Query all the home record(s) from file, totally get : 1 record(s)
- Query all the family member record(s) from file, totally get : 1 record(s)
更新home和member表的记录(可以看多了"O(∩_∩)O~~"的列) 控制台:
T_Home.db:[java] view plain copy
- Update one faminily member record - result: true ; description: The updated record is "Yan$_$Pery$_$Female$_$10086 O(∩_∩)O~~$_$ross.jiangtao.he@gmail.com$_$null$_$Ross_1" . It is update to "E:\myspace\MyJavaExpert V1.0\db\T_FamilyMember.db" successfully.
- Update one home record - result: true ; description: The updated record is "Ross_1$_$Pery's Home O(∩_∩)O~~$_$252363693$_$ross.jiangtao.he@gmail.com$_$China P.R." . It is update to "E:\myspace\MyJavaExpert V1.0\db\T_Home.db" successfully.
[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$phone$_$email$_$address
- #Content Start
- Ross_1$_$Pery's Home O(∩_∩)O~~$_$252363693 $_$ross.jiangtao.he @gmail .com$_$China P.R.
T_FamilyMember.db:
[java] view plain copy
- <pre name= "code" class = "java" >#Column Sequence
- ColumnSeq: id$_$name$_$gender$_$mobile$_$email$_$address$_$family_id
- #content start
- Yan$_$Pery$_$Female$_$10086 O(∩_∩)O~~$_$ross.jiangtao.he @gmail .com$_$ null $_$Ross_1
删除home和member表的一条记录 控制台:T_Home.db:[java] view plain copy
- Delete one faminily member record - result: true ; description: The deleted record is "Yan$_$Pery$_$Female$_$10086 O(∩_∩)O~~$_$ross.jiangtao.he@gmail.com$_$null$_$Ross_1" . It is delete from "E:\myspace\MyJavaExpert V1.0\db\T_FamilyMember.db" successfully.
- Delete one home record - result: true ; description: The deleted record is "Ross_1$_$Pery's Home O(∩_∩)O~~$_$252363693$_$ross.jiangtao.he@gmail.com$_$China P.R." . It is delete from "E:\myspace\MyJavaExpert V1.0\db\T_Home.db" successfully.
T_FamilyMember.db:[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$phone$_$email$_$address
- #Content Start
[java] view plain copy
- #Column Sequence
- ColumnSeq: id$_$name$_$gender$_$mobile$_$email$_$address$_$family_id
- #content start
至此" 文本数据库简单的实现思路 "已经完成了.
发表评论
-
<转>NetBeans 6.1 界面语言设置
2012-10-07 01:49 2354NetBeans 6.1 界面语言设置从官网下载的NetBea ... -
常见开源协议(BSD,Apache,GPL,LGPL,MIT)
2012-10-05 01:52 997BSD开源协议(original BSD license、Fr ... -
Java相对路径总结<转>
2012-03-04 17:16 10451.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或 ... -
Java Compiler 应用实例
2012-02-09 01:22 7074一直在用JDK1.5, 一直搞不清楚JDK1.6有啥特性, 就 ... -
java注解应用实例 - Annotation, 自定义注解, 注解类规则
2012-01-29 21:35 25685本文介绍了java的自定义注解及注解类编写的规则, 并通过实例 ... -
Java 序列化的高级认识--序列化反序列化, 加密存储<转>
2012-01-29 15:21 2316简介: 文章对序列化进行了更深一步的讨论,用实际的例子 ... -
java网络编程之Http多线程下载应用实例
2012-01-21 02:34 8728本demo 通过RandomAccessFile, URLC ... -
Java反射应用实例
2012-01-14 23:43 2158本文主要通过Java反射 ... -
java反射的性能问题 (转)
2012-01-14 23:36 2284很多IOC,还有框架都使用反射。特别是在通过反射调用方法的时候 ... -
java泛型应用实例 - 自定义泛型类,方法
2012-01-14 23:19 37517注: 转载请注明出处: http://hejiangtao.i ... -
泛型的效率和原始类的效率比较(转)
2012-01-14 23:16 1859用 了好久的泛型,突然听到有人说:泛型影响效率! 嘿, ...
相关推荐
- 使用Java设计并实现了一个简单的文本数据库系统。 - 数据的存储和检索通过Hashtable或类似数据结构(如TreeMap)实现,以键值对形式存储数据。 - 应用程序支持多线程环境,可能采用了线程安全的数据结构或同步机制...
一个Java纯文本数据库模型系统,正在开发中,有兴趣的话希望大家能帮助小弟改进。
本项目关注的是如何使用Java来实现读取Microsoft Word文件,并将其中的数据上传到数据库,以此提升数据录入的效率。这一过程涉及到多个技术点,包括文件I/O、Word文档解析、数据库操作以及可能的数据转换。 首先,...
在这个场景下,"java把文本文件内容导入到数据库"是一个典型的应用,它涉及到文本解析、数据库连接以及数据持久化等关键知识点。 首先,我们需要理解文本文件的格式。描述中提到文件内容的字段由“,”分隔,这种...
本文将深入探讨如何在Java环境中实现一个富文本编辑器的Demo,并讲解如何将编辑的数据存储到数据库以及在JSP中进行配置的修改。 首先,富文本编辑器的实现通常依赖于JavaScript库,如TinyMCE、CKEditor或Quill。...
标题中的“自动备份数据库java源码”指的是使用Java编程语言编写的一种程序,它的主要功能是自动化执行数据库的备份任务。数据库备份是数据保护的重要环节,它可以在数据丢失或系统故障时恢复数据,确保业务连续性。...
将本地硬盘中的文本数据读取到mysql的数据库表中。 1. 文件保存在本地目录下,按照固定的格式保存,每一行对应着数据库中的一条记录,属性用空格隔开。 2. 创建数据库表,字段需要和文本文件的数据逐列对应。 3. ...
内容概要:通过程序注释带着读者了解GUI界面构建过程,初步了解 java GUI的使用,理解GUI框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:登陆确认、随机出题、题目文本导入等内容实现。 适合人群:具备...
java 读取txt文本文件中的数据并保存到数据库中源代码,假设txt已有格式,并以","分隔。其中的sql包需要自己去微软官网下载。
在本文中,我们将深入探讨如何使用Java实现在本地读取图片并将其存储到数据库中,之后再通过HTML页面显示这些图片。这个过程涉及到的主要技术包括Java编程、数据库操作(特别是MySQL)以及前后端交互。 首先,我们...
标题中的“国产达梦数据库对应java-jdbc相关jar包”表明了这个压缩包包含的是用于连接达梦数据库的Java JDBC驱动程序。Java JDBC(Java Database Connectivity)是Java平台上的一个标准API,允许Java应用程序与各种...
【Java学生管理系统】是一个基于文本文件的简单应用,它不依赖任何数据库系统,而是通过读写TXT文件来存储和检索学生信息。这个管理系统的核心概念主要围绕着Java编程语言的文件操作、数据序列化和简单的数据结构。 ...
本人以JAVA来实现以支付宝的账单表为例,实现JAVA读取CSV..csv是一种文件格式(如.txt、.doc等),也可理解.csv文件就是一种特殊格式的纯文本文件。即是一组字符序列,字符之间已英文字符的逗号或制表符(Tab)分隔。
至于`文档.txt`,这可能是包含打包或数据库连接相关说明的文本文件。确保在发布程序时一并提供,以便用户参考。 总之,打包Java程序至JAR文件并连接MySQL数据库,需要正确管理依赖,选择合适的打包工具,如Eclipse...
在本项目中,"SERVLET技术实现数据库查询",意味着我们将探讨如何利用Servlet来与数据库进行交互,特别是MySQL数据库。SpringMVC是一个基于Spring框架的轻量级Web MVC框架,它简化了在Servlet中处理请求和响应的过程...
本主题探讨的是如何利用编程语言来读写文本文件,将其作为一种简易的数据库使用。这种方式虽然没有传统数据库那样复杂的功能,但在某些场景下却足够高效且易于实现。 首先,我们了解基本的文本文件操作。在大多数...
Java编写的数据库自动备份源码是一种实用的工具,它能够帮助数据库管理员定期、高效地创建数据库的备份,确保数据的安全性。在IT行业中,数据库管理是至关重要的,因为任何数据丢失都可能导致重大的业务损失。数据库...
此外,BufferedReader和PrintWriter类可以用于读写文本文件,如SQL脚本,这些脚本可能包含创建数据库表结构或插入初始数据的命令。 XML(Extensible Markup Language)则常用于存储和传输结构化数据。在Java中,...
本篇文章将探讨如何使用Java实现这一功能,特别是针对word、pdf、文本和图片等类型的文件进行对比计算,以及如何计算文本的相似率和筛选出差异的文件。 1. 文件和文件夹对比: 在Java中,可以使用`java.io.File`类...