• Android数据库无缝升级方案


    软件迭代过程中,业务不断更新,也要求软件持续更新。相应地,数据库更新升级也是不可避免的一个环节。Android作为客户端应用,数据库升级相对于服务端来说会麻烦一些。常见的升级方式有:

      1.删除旧表和数据,创建新表。优点是简单方便,缺点是丢失了旧数据。适用于应用数据依赖度低的情况。

      2.在代码中兼容处理各版本数据库,创建新表,迁移旧数据到新表。优点是保留了旧数据,缺点是需要处理兼容个版本数据库差异,比较麻烦。如果通过代码来记录维护版本差异,会导致代码臃肿且极易出错。

    本文介绍一种简单无缝的数据库升级方案,也是属于上述的第二种方式,但是简单、高效地处理了数据库版本兼容。代码已实现在DBFramework中,这是一个轻量的数据库框架,简单、规范、高效,能够很好的处理表之间的继承关系,可以为你节省很多开发工作。

    感兴趣的朋友可以了解一下。

    数据库升级,其实是对其中的表进行升级。要更新表并且保留数据,这就必须要知道新表和旧表之间的差异。如果我们靠开发人员来记录各版本之间表的差异,无疑是一个困难和繁杂的工作。那么当我们进行数据库的时候,客户端应用有没有办法知道这些差异,知道有哪些表需要更新呢?答案是肯定的。在Sqlite中有一张叫做sqlite_master的系统表,其中记录了sqlite中的所有表信息,如下:

    可以看到,其中除了表名,还有表创建语句。有了创建语句,我们就能解析出表的字段信息,然后对比新表和旧表的字段,有差异则说明表需要更新,反之则不需要更新。如下代码用来获取现有的表信息:

    /**
         * Get old tables.
         * @return A map contains old tables which takes table name as key.
         */
        public Map<String, Table> getOldTables() {
            final String table = "sqlite_master";
            final String[] columns = {"name", "sql"};
            Cursor cursor = mDB.query(table, columns, "type='table'", null, null, null, null);
            HashMap<String, Table> ret = null;
            if (cursor.getCount() > 0) {
                ret = new HashMap<String, Table>(cursor.getCount());
                Table tmp;
                while (cursor.moveToNext()) {
                    tmp = new Table(cursor.getString(0), cursor.getString(1));
                    ret.put(tmp.Name, tmp);
                }
            }
            cursor.close();
            return ret == null ? Collections.EMPTY_MAP : ret;
        }

    Table是一个记录表信息的类,拿到现有表信息,就可以和新的表信息进行对比,主要对比表字段的变化:

      public class Table {
    
       ...
    
      public boolean equalsColumns(Table table) {
            String myColumns = getColumnsStatement(CreateSql).toUpperCase();
            String columns = getColumnsStatement(table.CreateSql).toUpperCase();
            return (myColumns.equals(columns));
        }
    
       ...
    
    }

     如果无变化则跳过,有变化则更新,更新过程为:

    1.将现有表以别名命名

    2.创建新表

    3.迁移数据

    4.删除现有表

     如下代码所示:

     @Override
        protected void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion, List<Table> tableList) {
            Map<String, Table> oldMap = getOldTables();
            Iterator<Table> iterator = tableList.iterator();
            Table table;
            Table oldTable;
            String tempTable;
            while (iterator.hasNext()) {
                table = iterator.next();
                if ((oldTable = oldMap.get(table.Name)) == null) {
                    //New table, create directly.
                    db.execSQL(table.CreateSql);
                    Log.i(TAG, "Table " + table.Name + " is a new table. Create it directly");
                    continue;
                }
                //Remove hit table.
                oldMap.remove(table.Name);
                if (oldTable.equalsColumns(table)) {
                    //Table not change.
                    Log.i(TAG, "Table " + table.Name + " doesn't need update");
                    continue;
                }
                tempTable = table.Name + TEMP_SUFFIX;
                Log.i(TAG, "Update table: " + table.Name);
    
                //Table changed.
                //Alter old table as temp.
                alterTableName(oldTable.Name, tempTable);
                //Create new table.
                db.execSQL(table.CreateSql);
                //Copy data.
                copyData(getCommonColumn(oldTable.getColumns(), table.getColumns()), tempTable, table.Name);
                //Delete old table
                deleteTable(tempTable);
            }
            //Delete obsolete tables not hit.
            deleteObsoleteTables(oldMap.values());
        }

    更多细节可查看源码:DBFramework

    这种方案简单方便,而且几乎一劳永逸。推荐小伙伴们使用,如果有更好的方式或者宝贵意见,欢迎交流。

  • 相关阅读:
    Java hello/hi的简单的网络聊天程序
    案例分析:设计模式与代码的结构特性
    网络相关的命令工具研究报告
    如何提高程序员的键盘使用效率
    分析一套源代码的代码规范和风格并讨论如何改进优化代码
    用例建模Use Case Modeling
    结合工程实践选题调研分析同类软件产品
    领域建模
    SecureCRT 连接虚拟机Linux
    用css固定div层在页面顶部和底部(兼容IE6)
  • 原文地址:https://www.cnblogs.com/oxgen/p/7161986.html
Copyright © 2020-2023  润新知