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配置信息,應用的數據庫信息就創建出來了。

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM