Android之数据库—— 一个可配置的简易框架

前言

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




猜你喜欢

转载自blog.csdn.net/yangzhaomuma/article/details/51834575