標籤:orm 架構 opendroid
在上一篇部落格《打造android ORM架構opendroid(三)——持久化資料》中,我們感受到了opendroid儲存資料的流程,今天的部落格我們來順一下opendroid是如何刪除資料的。
還記得我們在第一篇部落格《打造android ORM架構opendroid(一)——ORM架構的使用》中介紹過opendroid的使用,先來回顧一下怎麼利用opendroid來刪除資料吧。
int length = OpenDroid.delete(Student.class, 1, 2, 3); System.out.println(length);
還有一種刪除資料的方式是使用where條。
int length = OpenDroid.delete(Student.class, "_id>?", "5"); System.out.println(length);
opendroid就這麼兩種刪除資料的方式,但這兩種方式已經可以適合大部分的需求了。
上面是回顧了一下opendroid的使用,但是我們今天的主題是瞭解opendroid是如何從資料庫中把資料刪除的。
所以...老規矩,首先定位到
OpenDroid.delete(Student.class, 1, 2, 3);
從最簡單開始入手吧!
/** * 刪除資料 * @param klass 要刪除的表對應的class * @param ids 資料的ids * @return 影響行數 */ public static <T extends OpenDroid> int delete(Class<T> klass, int... ids) { if(ids.length == 0) { return delete(klass, null, null); } StringBuilder builder = new StringBuilder("_id in ("); String[] whereArgs = new String[ids.length]; buildIn(builder, whereArgs, ids); return delete(klass, builder.toString(), whereArgs); }
根據id刪除的這個方法並不長,我們一句一句來分析一下。
首先8~10行,是一個判斷如果沒有設定id,則調用一個靜態delete方法,這個delete方法我們稍候去看,現在我們接著往下走代碼。
12行,用了一個StringBuilder來初始化一個in語句,從這裡我們可能已經清楚,使用這個delete方法刪除資料其實就是使用了sql語句的in操作。
13行,new了一個String類型的數組,數組的長度正好是ids的長度,為下面組件in語句做準備。
14行,我們調用了buildIn方法來構建一個in語句。
15行,直接調用了一個重載的delete的方法去刪除資料,這裡提一下,這個delete方法和我們上面if語句中調用的delete方法是同一個。
下面我們再來看看buildIn這個方法吧。
/** * 組裝IN語句 * @param builder in語句 * @param whereArgs in的內容 * @param ids 要拼裝的ids */ private static void buildIn(StringBuilder builder, String[] whereArgs, int... ids) { if(ids.length > 1) { for(int i=0;i<ids.length-1;i++) { whereArgs[i] = String.valueOf(ids[i]); builder.append("?,"); } } whereArgs[ids.length - 1] = String.valueOf(ids[ids.length - 1]); builder.append("?)"); }
縱觀整個buildIn方法也沒什麼痛點,這裡的作用就是拼裝一個 _id in(?,?,?)這樣形式的語句,並將ids放到上面我們初始化的那個String資料中,這樣我們是不是就已經準備好了sql預先處理中where的條件和條件的參數了呢?
當然這裡還有兩點可能感到迷惑的:
1、該方法為什麼沒有返回值? 這種寫法可能不是很常見,就是將返回值以參數的形式傳遞進來,大家都知道java的參數傳遞是按引用傳遞,所以只要不改變該參數指向地址,在該方法中對參數內容的修改是會影響調用者的。
2、for迴圈中為什麼是ids.length-1?因為我們需要的是(?,?,?)這樣的形式,最後一個?後是沒有“,”的,所以我們需要先拼裝前length-1個,然後在迴圈外面進行了最後的收尾工作。
這裡可能又會有朋友注意到,最後的收尾是在if外面進行的,這裡是不是寫錯了? 這裡是沒有錯的! 請看if的條件是什麼!
分析完buildIn後,我們再返回那個delete方法中,最後一句是調用了另一個delete方法,至於參數,大家肯定已經清楚參數的值了。
下面再來看看這個重載的delete方法吧。
/** * 刪除資料 * @param klass 要刪除的表對應的class * @param where where條件 * @param whereArgs where條件的參數 * @return 影響行數 */ public static <T extends OpenDroid> int delete(Class<T> klass, String where, String... whereArgs) { String tableName = klass.getSimpleName(); return CRUD.delete(tableName, where, whereArgs, sSqliteDatabase); }
哈哈,only兩行代碼,而且我們也驚奇的發現,這個方法也是我們上面第二種刪除的方式,太好了,兩種刪除方式最後還是會在同一個方法中碰面!
如此簡單,怎麼下手呢? 第1行代碼擷取了klass的類名,這裡代表的當然是我們刪除操作的表明了。
下一行中我們又去調用了CRUD.delete方法,那麼我們跟進代碼,去看看CRUD.delete吧。
/** * 刪除資料 * @param tableName 表名 * @param where where條件 * @param whereArgs where條件的參數 * @param db 資料庫 * @return 影響行數 */ protected static <T extends OpenDroid> int delete(String tableName, String where, String[] whereArgs, SQLiteDatabase db) { int count = db.delete(tableName, where, whereArgs); return count; }
又是兩行代碼!
首先來看看參數吧,第一個參數是要操作的表名,第二個參數是where條件,第三個參數是where條件的參數,第四個參數當然是我們操作資料庫的控制代碼了。
在代碼體中,第一句就去調用了android原生的delete操作去根據條件刪除資料,返回值是刪除的條目個數,緊接著返回該個數,CRUD.delete方法執行完畢!
這個刪除的條目個數會再次最多經過兩次返回,最終返回到我們的商務邏輯中。
最後,我們來回顧一下這個流程吧。
1、我們的代碼調用OpenDroid.delete方法
2、不管調用哪個重載的OpenDroid.delete方法,最後都會來到使用條件刪除的那個delete方法
3、使用id刪除,無非就是根據傳入的id和id個數來組件一個SQL的in語句
4、最後,在CRUD的delete方法中完成了資料的刪除,並返回影響行數。
opendroid的刪除操作我們已經順了一遍,看起來挺高端的,一看源碼是不是感覺如此簡單?
到現在為止,我們已經順完了opendroid的插入資料和刪除資料,在接下來的部落格中,還會繼續完成opendroid更新資料和查詢資料的代碼。
打造android ORM架構opendroid(四)——優雅的刪除資料