• 【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核心数据事实上就是记录,这个记录包含类别。时间,时间长度等字段值。

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


    当然这里仅仅是提供我的思路。其它更好的设计必定存在,希望您可以指导学习。






  • 相关阅读:
    Elasticsearch通关
    Zookeeper是什么
    手把手带你了解消息中间件(1)——基础
    为什么要分库分表
    mysql的innodb 引擎 表锁与行锁
    MySQL中Innodb的聚簇索引和非聚簇索引
    Redis主从和集群
    redis防止抢购商品超卖
    Laravel 核心--Facades 门面
    PHP数据库操作:使用ORM
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6897228.html
Copyright © 2020-2023  润新知