Android入门(十二)SQLite事务、升级数据库
原文鏈接:http://www.orlion.ga/610/
一、事務
????SQLite支持事務,看一下Android如何使用事務:比如 Book表中的數據都已經很老了,現在準備全部廢棄掉替換成新數據,可以先使用delete()方法將Book表中的數據刪除, 然后再使用insert()方法將新的數據添加到表中。我們要保證的是,刪除舊數據和添加新數據的操作必須一起完成,否則就還要繼續保留原來的舊數據。
????????????????Button?replaceData?=?(Button)?findViewById(R.id.replace_data);replaceData.setOnClickListener(new?View.OnClickListener()?{@Overridepublic?void?onClick(View?v)?{SQLiteDatabase?db?=?dbHelper.getWritableDatabase();db.beginTransaction();db.delete("book",?null,?null);try?{if?(true)?{//?手動拋出異常,讓事務失敗throw?new?Exception();}ContentValues?values?=?new?ContentValues();values.put("name",?"book?new");values.put("author",?"orlion");values.put("pages",?200);values.put("price",?100);db.insert("book",?null,?values);db.setTransactionSuccessful();?//?事務已經執行成功}?catch?(Exception?e)?{e.printStackTrace();}?finally?{db.endTransaction();?//?結束事務}}});????上述代碼就是Android中事務的標準用法, 首先調用SQLiteDatabase的beginTransaction()方法來開啟一個事務,然后在一個異常捕獲的代碼塊中去執行具體的數據庫操作,當所有的操作都完成之后,調用 setTransactionSuccessful()表示事務已經執行成功了,最后在 finally代碼塊中調用 endTransaction()來結束事務。注意觀察,我們在刪除舊數據的操作完成后手動拋出了一個 NullPointerException,這樣添加新數據的代碼就執行不到了。不過由于事務的存在,中途出現異常會導致事務的失敗,此時舊數據應該是刪除不掉的。
?
二、升級數據庫的最佳寫法
????// 這里直接復制《第一行代碼原文》
????Android入門(十)SQLite創建升級數據庫?一文中升級數據庫的方式是非常粗暴的,為了保證數據庫中的表是最新的,我們只是簡單地在 onUpgrade()方法中刪除掉了當前所有的表,然后強制重新執行了一遍 onCreate()方法。這種方式在產品的開發階段確實可以用,但是當產品真正上線了之后就絕對不行了。
????每一個數據庫版本都會對應一個版本號, 當指定的數據庫版本號大于當前數據庫版本號的時候, 就會進入到 onUpgrade()
方法中去執行更新操作。這里需要為每一個版本號賦予它各自改變的內容,然后在onUpgrade()方法中對當前數據庫的版本號進行判斷,再執行相應的改變就可以了。
????接著就讓我們來模擬一個數據庫升級的案例,還是由 MyDatabaseHelper類來對數據庫進行管理。第一版的程序要求非常簡單,只需要創建一張 Book表,MyDatabaseHelper中的代碼如下所示:
????
public?class?MyDatabaseHelper?extends?SQLiteOpenHelper?{public?static?final?String?CREATE_BOOK?=?"create?table?Book?("+?"id?integer?primary?key?autoincrement,?"+?"author?text,?"+?"price?real,?"+?"pages?integer,?"+?"name?text)";public?MyDatabaseHelper(Context?context,?String?name,?CursorFactoryfactory,?int?version)?{super(context,?name,?factory,?version);}@Overridepublic?void?onCreate(SQLiteDatabase?db)?{db.execSQL(CREATE_BOOK);}@Overridepublic?void?onUpgrade(SQLiteDatabase?db,?int?oldVersion,?int?newVersion)?{} }????不過,幾星期之后又有了新需求,這次需要向數據庫中再添加一張 Category表。于是,修改 MyDatabaseHelper中的代碼,如下所示:
public?class?MyDatabaseHelper?extends?SQLiteOpenHelper?{public?static?final?String?CREATE_BOOK?=?"create?table?Book?("+?"id?integer?primary?key?autoincrement,?"+?"author?text,?"+?"price?real,?"+?"pages?integer,?"+?"name?text)";public?static?final?String?CREATE_CATEGORY?=?"create?table?Category?("+?"id?integer?primary?key?autoincrement,?"+?"category_name?text,?"+?"category_code?integer)";public?MyDatabaseHelper(Context?context,?String?name,CursorFactory?factory,?int?version)?{super(context,?name,?factory,?version);}@Overridepublic?void?onCreate(SQLiteDatabase?db)?{db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);}@Overridepublic?void?onUpgrade(SQLiteDatabase?db,?int?oldVersion,?int?newVersion)?{switch?(oldVersion)?{case?1:db.execSQL(CREATE_CATEGORY);default:}} }????可以看到,在 onCreate()方法里我們新增了一條建表語句,然后又在 onUpgrade()方法中添加了一個 switch判斷,如果用戶當前數據庫的版本號是 1,就只會創建一張 Category表。這樣當用戶是直接安裝的第二版的程序時,就會將兩張表一起創建。而當用戶是使用第二版的程序覆蓋安裝第一版的程序時,就會進入到升級數據庫的操作中,此時由于 Book表已經存在了,因此只需要創建一張 Category表即可。但是沒過多久,新的需求又來了,這次要給 Book表和 Category表之間建立關聯,需要在 Book表中添加一個 category_id的字段。 再次修改 MyDatabaseHelper中的代碼, 如下所示:
public?class?MyDatabaseHelper?extends?SQLiteOpenHelper?{public?static?final?String?CREATE_BOOK?=?"create?table?Book?("+?"id?integer?primary?key?autoincrement,?"+?"author?text,?"+?"price?real,?"+?"pages?integer,?"+?"name?text,?"+?"category_id?integer)";public?static?final?String?CREATE_CATEGORY?=?"create?table?Category?("+?"id?integer?primary?key?autoincrement,?"+?"category_name?text,?"+?"category_code?integer)";public?MyDatabaseHelper(Context?context,?String?name,CursorFactory?factory,?int?version)?{super(context,?name,?factory,?version);}@Overridepublic?void?onCreate(SQLiteDatabase?db)?{db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);}@Overridepublic?void?onUpgrade(SQLiteDatabase?db,?int?oldVersion,?int?newVersion)?{switch?(oldVersion)?{case?1:db.execSQL(CREATE_CATEGORY);case?2:db.execSQL("alter?table?Book?add?column?category_id?integer");default:}} }????可以看到,首先我們在 Book表的建表語句中添加了一個 category_id列,這樣當用戶直接安裝第三版的程序時,這個新增的列就已經自動添加成功了。然而,如果用戶之前已經安裝了某一版本的程序,現在需要覆蓋安裝,就會進入到升級數據庫的操作中。在 onUpgrade()方法里,我們添加了一個新的 case,如果當前數據庫的版本號是 2,就會執行 alter命令來為Book表新增一個 category_id列。
????這里請注意一個非常重要的細節,switch中每一個 case的最后都是沒有使用 break的,為什么要這么做呢?這是為了保證在跨版本升級的時候, 每一次的數據庫修改都能被全部執行到。比如用戶當前是從第二版程序升級到第三版程序的,那么 case 2中的邏輯就會執行。而如果用戶是直接從第一版程序升級到第三版程序的,那么 case 1和 case 2中的邏輯都會執行。使用這種方式來維護數據庫的升級,不管版本怎樣更新,都可以保證數據庫的表結構是最新的,而且表中的數據也完全不會丟失了。
轉載于:https://www.cnblogs.com/orlion/p/5350683.html
總結
以上是生活随笔為你收集整理的Android入门(十二)SQLite事务、升级数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第八次课作业(采购管理、信息与配置管理)
- 下一篇: 堆排序\链表实现局部排序