前言
Android自带的Sqlite数据库是日常开发中必用的。这里介绍一种用xml形式配置数据库的简易框架(库)。
为什么要用这个框架?
(1)因为XML格式的配置方式,层次明显,一目了然;
(2)在扩展,对增减数据库中的表或者列,更加容易且不容易出错;
(3)将配置统一在XML中,对以后的维护,会显得十分方便;
(4)最后,是这个框架很简单。
一、设计
1、你首先要有一个XML文件,你要想象XML文件是个什么样子的,要包含哪些必要东西?
(1)最外层节点
数据库名要有;
数据库版本要有;
(2)次外层节点
表名要有;
(3)内层节点
列名要有;
主键要有;
根据以上的必要元素,我们做了一个XML文件:
<?xml version="1.0" encoding="utf-8"?>
<!-- 数据库定义 -->
<Database
name="databaseMe.db"
version="1" >
<!-- 交易数据保存 -->
<table
name="Mydata"
primaryKey="id" >
<field name="id" /> <!-- 主键,只能自增长的integer -->
<field name="name" />
<field name="adress" />
</table>
</Database>
根据这些元素,我们应该能够生成一个名为databaseMe.db的数据库,库中含有表Mydata,表中有三列,分别为id,name,adress,其中id是主键。
要实现以上描述的功能,我们还需要写一些代码。
2、代码应该如何设计?
(1)首先要解析xml文件;
(2)看这个xml文件,它只有三个节点,Database、table、field,分别是数据库、表、列,其他的都是xml的属性值。
(3)我们用代码解析xml内容,并根据内容,创建出数据库以及它的表、列。
根据这上面的代码设计,打算用javaBean方式,一层一层的把代码写好。
二、具体实施
根据xml文件,我们写出三个Model。
数据库:
package com.database.lib;
import java.util.List;
public class DataBaseModel {
//数据库名称
private String dataBaseName;
//数据库版本
private int dataBaseVersion;
//数据库中表集合
private List<DataBaseTableModel> tables;
public List<DataBaseTableModel> getTables() {
return tables;
}
public void setTables(List<DataBaseTableModel> tables) {
this.tables = tables;
}
public String getDataBaseName() {
return dataBaseName;
}
public void setDataBaseName(String dataBaseName) {
this.dataBaseName = dataBaseName;
}
public int getDataBaseVersion() {
return dataBaseVersion;
}
public void setDataBaseVersion(int dataBaseVersion) {
this.dataBaseVersion = dataBaseVersion;
}
}
表:
package com.database.lib;
import java.util.List;
public class DataBaseTableModel {
//表名
private String tableName;
//主键
private String primaryKey;
//表结构
private List<DataBaseFieldModel> fields;
public List<DataBaseFieldModel> getFields() {
return fields;
}
public void setFields(List<DataBaseFieldModel> fields) {
this.fields = fields;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(String primaryKey) {
this.primaryKey = primaryKey;
}
}
列:
package com.database.lib;
public class DataBaseFieldModel {
//列名
private String name;
//列其他属性,暂忽略,有需要可添加...
public String getFieldName() {
return name;
}
public void setFieldName(String name) {
this.name = name;
}
}
而解析XML文件上,采用了SAX+DefaultHandler方式来解析。具体的代码如下,代码中有注释:
/**
* 将XML文件解析为DataBaseModle
* @param xmlFile
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
private DataBaseModel getDataBase(String xmlFile) throws ParserConfigurationException, SAXException, IOException{
//读取xml文件
InputStream in=context.getResources().getAssets().open(xmlFile);
//SAX解析
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser= factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
//DefaultHandler配合SAX解析xml内容
DataBaseHandler mHandler=new DataBaseHandler();
reader.setContentHandler(mHandler);
reader.parse(new InputSource(new InputStreamReader(in, "UTF-8")));
//将解析得到的内容导致到model中
DataBaseModel model=new DataBaseModel();
model.setDataBaseName(mHandler.getDataBaseName());
model.setDataBaseVersion(mHandler.getDataBaseVersion());
model.setTables(mHandler.getTables());
return model;
}
以下是DefaultHandler的实现:
package com.database.lib;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class DataBaseHandler extends DefaultHandler{
private String dataBaseName;
private int dataBaseVersion;
private List<DataBaseTableModel> tables;
private DataBaseTableModel table;
private List<DataBaseFieldModel> fields;
@Override
public void startDocument() throws SAXException {
tables=new ArrayList<DataBaseTableModel>();
fields=new ArrayList<DataBaseFieldModel>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (DataBaseManager.DATABASE.equals(qName)) {
dataBaseName = attributes.getValue(DataBaseManager.DATABASE_NAME);
dataBaseVersion = Integer.parseInt(attributes.getValue(DataBaseManager.DATABASE_VERSION));
} else if (DataBaseManager.TABLE.equals(qName)) {
table =new DataBaseTableModel();
String name=attributes.getValue(DataBaseManager.TABLE_NAME);
String primarykey = attributes.getValue(DataBaseManager.TABLE_PRIMARYKEY);
table.setTableName(name);
table.setPrimaryKey(primarykey);
} else if (DataBaseManager.FIELD.equals(qName)) {
try {
String filed = attributes.getValue(DataBaseManager.FIELD_NAME);
DataBaseFieldModel fieldModel=new DataBaseFieldModel();
fieldModel.setFieldName(filed);
fields.add(fieldModel);
table.setFields(fields);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (DataBaseManager.TABLE.equals(qName)) {
tables.add(table);
}
}
public String getDataBaseName() {
return dataBaseName;
}
public void setDataBaseName(String dataBaseName) {
this.dataBaseName = dataBaseName;
}
public int getDataBaseVersion() {
return dataBaseVersion;
}
public void setDataBaseVersion(int dataBaseVersion) {
this.dataBaseVersion = dataBaseVersion;
}
public List<DataBaseTableModel> getTables() {
return tables;
}
public void setTables(List<DataBaseTableModel> tables) {
this.tables = tables;
}
}
通过以上的方式,我们已经把xml内容都成功的写入到了对应的model中,现在就剩下最后一步:创建数据库以及它的表、列。用我们都熟悉的方法来实现:
package com.database.lib;
import java.util.List;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
private DataBaseModel model;
public DataBaseHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
public DataBaseHelper(Context context, DataBaseModel model) {
super(context, model.getDataBaseName(), null, model.getDataBaseVersion());
this.model=model;
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
if(model.getTables().size()>0){
for(DataBaseTableModel tableModel:model.getTables()){
createTable(db,tableModel);
}
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
private void createTable(SQLiteDatabase db, DataBaseTableModel table) {
StringBuilder sql = new StringBuilder(" create table if not exists ");
String tableName = table.getTableName();
String primaryKey = table.getPrimaryKey();
List<DataBaseFieldModel> fileds = table.getFields();
sql.append(tableName);
sql.append("(");
int i = 0;
for (i = 0; i < fileds.size(); i++) {
if (i == fileds.size() - 1) {
if (fileds.get(i).getFieldName().equals(primaryKey)) {
sql.append(fileds.get(i).getFieldName() + " integer primary key autoincrement");
} else{
sql.append(fileds.get(i).getFieldName() + " TEXT)");
}
} else {
if (fileds.get(i).getFieldName().equals(primaryKey)) {
sql.append(fileds.get(i).getFieldName() + " integer primary key autoincrement,");
} else{
sql.append(fileds.get(i).getFieldName() + " TEXT,");
}
}
}
db.execSQL(sql.toString());
}
}
到这里为止,你其实已经完整的创建了数据库。为了方便使用,再做一层封装,也就是对外开放的类:
package com.database.lib;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
public class DataBaseManager {
private Context context;
private DataBaseHelper mHelper;
private SQLiteDatabase db;
public static final String DATABASE="Database";
public static final String TABLE="table";
public static final String FIELD="field";
public static final String DATABASE_NAME="name";
public static final String DATABASE_VERSION="version";
public static final String TABLE_NAME="name";
public static final String TABLE_PRIMARYKEY="primaryKey";
public static final String FIELD_NAME="name";
private DataBaseManager(){}
private volatile static DataBaseManager instance;
public static DataBaseManager getInstance(){
if(instance==null){
synchronized (DataBaseManager.class) {
instance=new DataBaseManager();
}
}
return instance;
}
public void init(Context context){
this.context=context;
try {
DataBaseModel dataBaseModel=getDataBase("database.xml");
mHelper=new DataBaseHelper(context, dataBaseModel);
db=mHelper.getWritableDatabase();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 将XML文件解析为DataBaseModle
* @param xmlFile
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
private DataBaseModel getDataBase(String xmlFile) throws ParserConfigurationException, SAXException, IOException{
//读取xml文件
InputStream in=context.getResources().getAssets().open(xmlFile);
//SAX解析
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser= factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
//DefaultHandler配合SAX解析xml内容
DataBaseHandler mHandler=new DataBaseHandler();
reader.setContentHandler(mHandler);
reader.parse(new InputSource(new InputStreamReader(in, "UTF-8")));
//将解析得到的内容导致到model中
DataBaseModel model=new DataBaseModel();
model.setDataBaseName(mHandler.getDataBaseName());
model.setDataBaseVersion(mHandler.getDataBaseVersion());
model.setTables(mHandler.getTables());
return model;
}
/**
* 增
* @param table
* @param values
* @return
*/
public long insertData(String table,ContentValues values){
return 0;
}
/**
* 查
* @param sql
*/
public void selectData(String sql){
}
/**
* 改
* @param sql
*/
public void modifyData(String sql){
}
/**
* 删
* @param sql
*/
public void deleteData(String sql){
}
}
OK,现在你可以很轻易的初始化这个数据库了,你只需要这样:
DataBaseManager.getInstance().init(this);
你就完成了数据库、表、列的创建,后续的扩展也很方便。
这个简易框架,对于简单的数据库而言,还是很方便和节省时间的。
另外,说一下不足的地方:因为这是个很简单的框架,并没有对列的属性做扩展,目前只有Text一个属性。如果需要扩展,可能框架就变的较为复杂。有需要的可以在Field中写上你需要的属性,比如长度限制等,在DataBaseHandler中解析出来就好(当然,别忘了在DataBaseFieldModel中加上你定义的属性名称)。
三、源码
github上源码(AndroidStudio版本):https://github.com/yangzhaomuma/DataBaseManager
csdn上源码(eclipse 版本):http://download.csdn.net/detail/yangzhaomuma/9568138