zoukankan      html  css  js  c++  java
  • Android数据库表的创建和数据升级操作

        之前的文章有提到,可以在xml文件中配置数据库信息:http://www.cnblogs.com/wenjiang/p/4492303.html,现在就讲如何利用这些信息类构建数据库。

        xml文件大概如下:

    <?xml version="1.0" encoding="utf-8"?>
    <database>
        <!-- 数据库名称 -->
        <dbname value="zwb.db"></dbname>
    
        <!-- 数据库版本 -->
        <version value="1"></version>
    
        <!-- 数据库表 -->
        <list>
            <mapping class="com.zwb.args.dbpratice.model.Status"></mapping>
            <mapping class="com.zwb.args.dbpratice.model.User"></mapping>
        </list>
    </database>

        读取出来的信息其实很简单:数据库名字,数据库版本和数据库表。

        Android原本就提供了SQLiteOpenHelper来帮助我们完成数据库的一些基本操作,所以这里还是需要实现SQLiteOpenHelper的。

        定义一个SQLiteOpenHelper,在初始化的时候将数据库名字和数据库版本传进去:

     public BaseSQLiteOpenHelper(Context context, String name, int version) {
        super(context, name, null, version);
    }

         接下来就是在onCreate方法中实现创建表的动作:

         考虑到数据升级的问题,我将有关数据升级的操作都放在一个方法中,然后在onUpgrade方法中调用onCreate就行了。

         这里只考虑数据升级的问题,当然,降级也是可以的,不过一般这种情况在移动端比较少见。

         之前将包含数据库的表名的List存储进SharedPreferencesManager中,当然,一般的SharedPreferencesManager是不能存储容器类的,但这里我进行了扩展,具体的实现后面有需要再拿出来。

         数据库是在xml文件中配置数据库表的信息,所以必须判断从xml文件中读取出来的数据库信息是否还是和之前一致,如果原先的配置信息没有的话,就要创建表(哪怕只是修改表名,都当做是重新创建表,这是无可置疑的,因为修改旧表后还指望能够将数据迁移到新表中,说明一开始建表时候实在是太草率了。。。),如果原先的配置有,现在没有,说明是要删除旧表。

    List<String> oldTableList = SharedPreferencesManager.getInstance().getListString("tables");
    if (oldTableList.size() != 0) {
    
         for (String table : oldTableList) {
              if (!DatabaseCache.tableSet.contains(table)) {
                    dropTable(db, table);
              }
         }
    
         for (String table : DatabaseCache.tableSet) {
               if (!oldTableList.contains(table)) {
                    createTable(db, table);
               }
          }
    }

          dropTable的实现非常简单:

     String deleteSql = "drop table if exists " + table;
     db.execSQL(deleteSql);

          createTable的实现也不复杂,同样是拼接SQL语句:

        private void createTable(SQLiteDatabase db, String table) {
            try {
                StringBuilder sql = new StringBuilder("create table if not exists ");
                BaseTable entity = (BaseTable) (Class.forName(table).newInstance());
                String tableName = getTableName(entity);
                sql.append(tableName);
                sql.append(" (id integer primary key autoincrement, ");
                List<String> columnList = getColumns(entity);
                for (int i = 0, length = columnList.size(); i < length; i++) {
                    sql.append(columnList.get(i) + " ");
                    if (i == length - 1) {
                        break;
                    }
                    sql.append(", ");
                }
                sql.append(");");
                db.execSQL(sql.toString());
            } catch (InstantiationException e) {
                LogUtil.e(e.toString());
            } catch (IllegalAccessException e) {
                LogUtil.e(e.toString());
            } catch (ClassNotFoundException e) {
                LogUtil.e(e.toString());
            } catch (NoSuchTableException e) {
                LogUtil.e(e.toString());
            }
        }

           Android本身也提供了对SQL语句的封装,但实际上,使用Android的API还是不如自己写SQL。。。

           如果应用是第一次安装,那么数据库的创建动作就结束了,最后只要将新的配置信息存储到SharedPreferencesManager中就行。

           但如果是数据库升级,在执行完上面的操作,表是该删的删,该建的的建,但如果要做数据迁移,比如说,某张表增加了一些字段(这里不做删除字段的处理,就算有多余字段的数据保留也并不是个问题,比起丢失数据的严重性来说,一定程度的冗余字段还是可以接受的)。

           实现也是比较简单,就是几个步骤:将旧表重命名为一个临时表保存数据,创建旧表,将临时表的数据迁移到旧表中,删除临时表,每个步骤都是SQL语句的拼接而已:

           for (String tableEntity : DatabaseCache.tableSet) {
                try {
                    BaseTable entity = (BaseTable) (Class.forName(tableEntity).newInstance());
                    db.beginTransaction();
                    String table = getTableName(entity);
                    String selectSql = "select * from " + table;
                    Cursor cursor = db.rawQuery(selectSql, null);
                    List<String> oldColumns = new ArrayList<>();
                    for (String column : cursor.getColumnNames()) {
                        oldColumns.add(column);
                    }
                    String alterSql = "alter table " + table + " rename to " + table + "_temp";
                    db.execSQL(alterSql);
    
                    createTable(db, tableEntity);
    
                    List<String> newColumns = getColumnFrom(tableEntity);
                    StringBuilder upgradeSqlBuilder = new StringBuilder("insert into " + table + " select id, ");
                    int i = 0;
                    for (String column : newColumns) {
                        if (oldColumns.contains(column)) {
                            upgradeSqlBuilder.append(column + ", ");
                            i++;
                        }
                    }
    
                    if ((i != 0) && (i < newColumns.size())) {
                        for (int j = 0, length = newColumns.size() - i; j < length; j++) {
                            upgradeSqlBuilder.append("'', ");
                        }
                    }
    
                    String upgradeStr = upgradeSqlBuilder.toString();
                    String upgradeSql = upgradeStr.substring(0, upgradeStr.length() - 2) + " from " + table + "_temp";
                    db.execSQL(upgradeSql);
                    dropTable(db, table + "_temp");
                    db.setTransactionSuccessful();
                    db.endTransaction();
                } catch (InstantiationException e) {
                    LogUtil.e(e.toString());
                } catch (IllegalAccessException e) {
                    LogUtil.e(e.toString());
                } catch (ClassNotFoundException e) {
                    LogUtil.e(e.toString());
                } catch (NoSuchTableException e) {
                    LogUtil.e(e.toString());
                }
            }

          由于涉及到的数据库操作比较多,我就将这些操作放在事务中执行。

          到了这里,根据读取的xml配置信息,应用的数据库信息就创建出来了。

        

  • 相关阅读:
    杭电 Problem
    杭电Problem 5053 the sum of cube 【数学公式】
    杭电 Problem 2089 不要62 【打表】
    杭电 Problem 4548 美素数【打表】
    杭电 Problem 2008 分拆素数和 【打表】
    杭电 Problem 1722 Cake 【gcd】
    杭电 Problem 2187 悼念512汶川大地震遇难同胞——老人是真饿了【贪心】
    杭电Problem 1872 稳定排序
    杭电 Problem 1753 大明A+B
    东北林业大 564 汉诺塔
  • 原文地址:https://www.cnblogs.com/wenjiang/p/4557196.html
Copyright © 2011-2022 走看看