首页 > 代码库 > 【Android 开发实例】时间管理APP开发之数据库设计

【Android 开发实例】时间管理APP开发之数据库设计

当然也可以先写界面什么的,但是,总觉得先把数据库后台写好在写界面比较放心。

对于数据库的设计,我一开始没什么概念,甚至不知道如何下手,一开始想着设计成几个表?有哪些字段?

最后用了两天时间,还是一无所获。


最后参照着数据库系统概论课的一些东西以及查看别的项目的源码,才大概的确定数据库。

因为这个APP的类别被我确定只能是二级类别。所以我设计成三个表:

总类表,子类表,详细记录表。

(程序代码中出现的Log语句仅为我自己测试输出使用的)

代码如下:

package suool.net.timesumlbxf.db;

/**
 * Created by SuooL on 2014/10/6.
 */
public class TimeSumDBInfo {
    private static String TableNames[] = {
            "TBL_EXPENDITURE_CATEGORY",        // 时间花费类别数据库表
            "TBL_EXPENDITURE_SUB_CATEGORY",    // 时间花费子类别数据库表
            "TBL_EXPENDITURE"                  // 时间花费数据库表
    };//表名


    private static String FieldNames[][] = {
            {"ID","NAME"},
            {"ID","NAME","PARENT_CATEGORY_ID"},
            {"ID", "AMOUNT", "EXPENDITURE_CATEGORY_ID",
                    "EXPENDITURE_SUB_CATEGORY_ID","DATE", "TIME","MEMO"}
    };//字段名

    private static String FieldTypes[][] = {
            {"INTEGER PRIMARY KEY AUTOINCREMENT","text"},
            {"INTEGER PRIMARY KEY AUTOINCREMENT","TEXT","INTEGER"},
            {"INTEGER PRIMARY KEY AUTOINCREMENT","DOUBLE",
                    "INTEGER","INTEGER","TEXT","TEXT","TEXT"}
    };//字段类型

    public TimeSumDBInfo() {
        // TODO Auto-generated constructor stub
    }

    public static String[] getTableNames() {
        return TableNames;
    }

    public static String[][] getFieldNames() {
        return FieldNames;
    }

    public static String[][] getFieldTypes() {
        return FieldTypes;
    }
}

这个是数据库基本属性,具体的数据库创建和方法抽象如下:

package suool.net.timesumlbxf.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.nfc.Tag;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by SuooL on 2014/10/6.
 */
public class DBHelper extends SQLiteOpenHelper {
    public static final String TAG = "MyTest";

    private DBHelper mDbHelper;    //SQLiteOpenHelper实例对象
    private SQLiteDatabase mDb;    //数据库实例对象
    private static DBHelper openHelper = null;//数据库调用实例

    private static String TableNames[];     //表名
    private static String FieldNames[][];   //字段名
    private static String FieldTypes[][];   //字段类型

    private static String NO_CREATE_TABLES = "no tables";
    private static String message = "";

    private final Context mCtx;    //上下文实例

    // 构造方法
    private DBHelper(Context context, String myDBName, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, myDBName, factory, version);
        mCtx = context;
    }

    // 获取DBHelper实例
    public static DBHelper getInstance(Context context, String myDBName,
                                       SQLiteDatabase.CursorFactory factory, int version) {
        if (openHelper == null) {
            openHelper = new DBHelper(context, myDBName, factory, version);
            TableNames = TimeSumDBInfo.getTableNames();
            FieldNames = TimeSumDBInfo.getFieldNames();
            FieldTypes = TimeSumDBInfo.getFieldTypes();
        }

        Log.d(TAG, "" + TableNames.length);
        return openHelper;
    }

    // 创建数据库动作
    @Override
    public void onCreate(SQLiteDatabase db) {
        if (TableNames == null) {
            message = NO_CREATE_TABLES;
            Log.d(TAG, message);
            return;
        }
        for (int i = 0; i < TableNames.length; i++) {
            String sql2 = "CREATE TABLE " + TableNames[i] + " (";
            for (int j = 0; j < FieldNames[i].length; j++) {
                sql2 += FieldNames[i][j] + " " + FieldTypes[i][j] + ",";
            }
            sql2 = sql2.substring(0, sql2.length() - 1);
            sql2 += ")";
            Log.d(TAG, "自动组装的sql语句."+sql2);
            db.execSQL(sql2);  // 执行语句
        }
        Log.d(TAG,"数据库创建成功.");
    }

    // 更新数据库
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        for (int i = 0; i < TableNames[i].length(); i++) {
            String sql = "DROP TABLE IF EXISTS " + TableNames[i];  // 存在则删除
            db.execSQL(sql);
        }
        onCreate(db);   // 执行创建数据库语句
    }

    /**
     * 添加数据库相关信息
     */
    public void insertTables(String[] tableNames, String[][] fieldNames, String[][] fieldTypes) {
        TableNames = tableNames;
        FieldNames = fieldNames;
        FieldTypes = fieldTypes;
    }


    /**
     * 关闭数据库
     */
    public void close() {
        mDbHelper.close();
    }

    public void execSQL(String sql) throws java.sql.SQLException {
        mDb.execSQL(sql);
    }

    /**
     * sql语句查询数据
     */
    public Cursor rawQuery(String sql, String[] selectionArgs) {
        Cursor cursor = mDb.rawQuery(sql, selectionArgs);
        return cursor;
    }

    /**
     * 查询数据
     */
    public Cursor select(String table, String[] columns,
                         String selection, String[] selectionArgs, String groupBy,
                         String having, String orderBy) {
        Cursor cursor = mDb.query
                (
                        table, columns, selection, selectionArgs,
                        groupBy, having, orderBy
                );
        return cursor;
    }

    /**
     * 添加数据
     */
    public long insert(String table, String fields[], String values[]) {
        ContentValues cv = new ContentValues();
        for (int i = 0; i < fields.length; i++) {
            cv.put(fields[i], values[i]);
        }
        return mDb.insert(table, null, cv);
    }

    /**
     * 删除数据
     */
    public int delete(String table, String where, String[] whereValue) {
        return mDb.delete(table, where, whereValue);
    }

    /**
     * 更新数据
     */
    public int update(String table, String updateFields[],
                      String updateValues[], String where, String[] whereValue) {
        ContentValues cv = new ContentValues();
        for (int i = 0; i < updateFields.length; i++) {
            cv.put(updateFields[i], updateValues[i]);
        }
        return mDb.update(table, cv, where, whereValue);
    }

    /**
     * 错误信息: 不为null数据库未建立
     */
    public String getMessage() {
        return message;
    }
}

数据相关的默认字段值如下,计划着这些项目都是可以实现自定义添加和删除的。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 时间花费项目 -->
    <string-array name="TBL_EXPENDITURE_CATEGORY">
        <item>学习</item>
        <item>工作</item>
        <item>娱乐</item>
        <item>欢乐时光</item>
        <item>日常MISSION</item>
    </string-array>

    <!-- 时间花费子项目 -->
    <!-- 学习子项目 -->
    <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_1">
        <item>基础语言</item>
        <item>脚本语言</item>
        <item>Linux编程</item>
        <item>Android</item>
        <item>技术类书籍OR博客</item>
    </string-array>

    <!-- 工作项目 -->
    <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_2">
        <item>APP</item>
        <item>外包程序</item>
    </string-array>

    <!-- 娱乐子项目 -->
    <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_3">
        <item>电脑游戏</item>
        <item>手机游戏</item>
        <item>社交网络</item>
        <item>Music</item>
    </string-array>

    <!-- 欢乐时光子项目 -->
    <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_4">
        <item>文学阅读</item>
        <item>博客写作</item>
        <item>体育锻炼</item>
        <item>陪黎怡</item>
    </string-array>

    <!-- 日常任务列表 -->
    <string-array name="TBL_EXPENDITURE_SUB_CATEGORY_5">
        <item>2道算法题目</item>
        <item>单词50个或英语阅读</item>
        <item>技术博文1篇</item>
        <item>技术文章+笔记</item>
        <item>电子书1小时</item>
    </string-array>

    <!-- -->
    <string-array name="Hour">
        <item>0</item>
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
    </string-array>

    <string-array name="Minute">
        <item>0</item>
        <item>10</item>
        <item>20</item>
        <item>30</item>
        <item>40</item>
        <item>50</item>
    </string-array>

</resources>

在上面的时间长度被我固定了,其实用户自己输入任意数值,我刚开始是考虑有用户输入值,但是,后来一想觉得这个时间长度实在不是很精确的事情(做某件事具体的开始和结束界限不清,而且某段时间不一定全部用来做某件事),因此与其让用户花费时间计算精确,不如给个大概值选择就好。(四舍五入)。


ok,数据库的设计就是这样,做完这个感觉其实数据库的设计并不难,只要自己能够分析出所做的东西的focus在哪里就好了。

这个APP核心数据其实就是记录,这个记录包括类别,时间,时间长度等字段值。

但是又不可能只设计一个表,因为设计一个表不利于查询,而且造成数据冗余。因此就会产生将数据库设计成我上面代码所示的样子。


当然这里只是提供我的思路,其他更好的设计必然存在,希望您能够指导学习。






【Android 开发实例】时间管理APP开发之数据库设计