Android數據庫高手祕籍(六)——LitePal的修改和刪除操做

在上一篇文章中,咱們學會了使用LitePal進行存儲數據的功能。確實,比起直接使用Android原生的API,LitePal明顯簡單方便了太多。那麼,在增刪改查四種操做中,咱們已經把「增」學完了,今天就讓咱們繼續趁熱打鐵,學習一下如何使用LitePal進行修改和刪除操做。尚未看過前一篇文章的朋友建議先去參考 Android數據庫高手祕籍(五)——LitePal的存儲操做 。java

LitePal的項目地址是:https://github.com/LitePalFramework/LitePalgit

傳統的修改和刪除數據方式

上篇文章中咱們已經得知,SQLiteDatabase類中提供了一個insert()方法用於插入數據,那麼相似地,它還提供了update()和delete()這兩個方法,分別用於修改和刪除數據。先來看一下update()方法的方法定義:github

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片sql

  1. public int update(String table, ContentValues values, String whereClause, String[] whereArgs)  數據庫

update()方法接收四個參數,第一個參數是表名,第二個參數是一個封裝了待修改數據的ContentValues對象,第三和第四個參數用於指定修改哪些行,對應了SQL語句中的where部分。數組

那麼好比說咱們想把news表中id爲2的記錄的標題改爲「今日iPhone6發佈」,就能夠這樣寫:svg

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片學習

  1. SQLiteDatabase db = dbHelper.getWritableDatabase();  spa

  2. ContentValues values = new ContentValues();  .net

  3. values.put("title""今日iPhone6發佈");  

  4. db.update("news", values, "id = ?"new String[] {"2"});  

其做用至關於以下SQL語句:

[sql] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. update news set title='今日iPhone6發佈' where id=2;  

能夠看出,比起直接使用SQL語句,update()方法的語義性明顯更強,也更容易讓人理解。

接下來再看一下delete()方法的方法定義:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public int delete(String table, String whereClause, String[] whereArgs)  

delete()方法接收三個參數,第一個參數一樣是表名,第二和第三個參數用於指定刪除哪些行,對應了SQL語句中的where部分。

那麼好比說咱們想把news表中全部沒有評論的新聞都刪除掉,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. SQLiteDatabase db = dbHelper.getWritableDatabase();  

  2. db.delete("news""commentcount = ?"new String[] {"0"});  

其做用至關於以下SQL語句:

[sql] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. delete from news where commentcount=0;  

因而可知,Android給咱們提供的這些幫助方法,在很大程度上確實簡化了很多數據庫操做的複雜度。不過LitePal顯然作到了更好,下面就讓咱們學習一下如何使用LitePal來進行修改和刪除操做。

使用LitePal修改數據

LitePal修改數據的API比較簡單,並無什麼太多的用法,也比較好理解,方法都是定義在DataSupport類中的,咱們先來看一下方法定義:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public static int update(Class<?> modelClass, ContentValues values, long id)  

這個靜態的update()方法接收三個參數,第一個參數是Class,傳入咱們要修改的那個類的Class就好,第二個參數是ContentValues對象,這三個參數是一個指定的id,表示咱們要修改哪一行數據。

那麼好比說咱們想把news表中id爲2的記錄的標題改爲「今日iPhone6發佈」,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. ContentValues values = new ContentValues();  

  2. values.put("title""今日iPhone6發佈");  

  3. DataSupport.update(News.class, values, 2);  

能夠看出,整體來說仍是比原生的用法要簡單一些的,首先咱們避免掉了要去獲取SQLiteDatabase對象的步驟,其次在指定修改某一條id記錄的時候只須要傳入這個id便可,語法更簡練。

那麼有的朋友可能會問了,也許我想修改的是某一個條件下的全部數據,而不是僅僅修改某個id的數據,那該怎麼辦呢?別擔憂,LitePal還提供了另一個簡便的方法,方法定義以下:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public static int updateAll(Class<?> modelClass, ContentValues values, String... conditions)  

updateAll()方法表示修改多行記錄,其中第一個參數仍然是Class,第二個參數仍是ContentValues對象,第三個參數是一個conditions數組,用於指定修改哪些行的約束條件,返回值表示這次修改影響了多少行數據。

那麼好比說咱們想把news表中標題爲「今日iPhone6發佈」的全部新聞的標題改爲「今日iPhone6 Plus發佈」,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. ContentValues values = new ContentValues();  

  2. values.put("title""今日iPhone6 Plus發佈");  

  3. DataSupport.updateAll(News.class, values, "title = ?""今日iPhone6發佈");  

前面都沒什麼好說的,重點咱們看一下最後的這個conditions數組,因爲它的類型是一個String數組,咱們能夠在這裏填入任意多個String參數,其中最前面一個String參數用於指定約束條件,後面全部的String參數用於填充約束條件中的佔位符(即?號),好比約束條件中有一個佔位符,那麼後面就應該填寫一個參數,若是有兩個佔位符,後面就應該填寫兩個參數,以此類推。

好比說咱們想把news表中標題爲「今日iPhone6發佈」且評論數量大於0的全部新聞的標題改爲「今日iPhone6 Plus發佈」,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. ContentValues values = new ContentValues();  

  2. values.put("title""今日iPhone6 Plus發佈");  

  3. DataSupport.updateAll(News.class, values, "title = ? and commentcount > ?""今日iPhone6發佈""0");  

能夠看出,經過佔位符的方式來實現條件約束明顯要比原生的API更加簡單易用。

那麼若是咱們想把news表中全部新聞的標題都改爲「今日iPhone6發佈」,該怎麼寫呢?其實這就更簡單了,只須要把最後的約束條件去掉就好了,以下所示:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. ContentValues values = new ContentValues();  

  2. values.put("title""今日iPhone6 Plus發佈");  

  3. DataSupport.updateAll(News.class, values);  

怎麼樣,這種寫法是否是感受語義性很是強?updateAll()方法在不指定約束條件的狀況下就是修改全部行的數據,的的確確是update all了。

固然有些朋友可能會以爲這樣用起來仍是有點複雜,由於這個ContentValues對象很煩人,每次建立它的時候都要寫不少繁瑣的代碼。不要緊,LitePal也充分考慮了這種狀況,提供了一種不須要ContentValues就能修改數據的方法,下面咱們嘗試使用這種新方法來完成上述一樣的功能。

好比把news表中id爲2的記錄的標題改爲「今日iPhone6發佈」,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News updateNews = new News();  

  2. updateNews.setTitle("今日iPhone6發佈");  

  3. updateNews.update(2);  

此次咱們並無用ContentValues,而是new出了一個News對象,把要修改的數據直接set進去,最後調用一下update()方法並傳入id就能夠了。不只不用建立ContentValues對象,連表名都不用指定了,由於News對象默認就是修改的news表。

這是其中一種用法,那麼若是咱們想把news表中標題爲「今日iPhone6發佈」且評論數量大於0的全部新聞的標題改爲「今日iPhone6 Plus發佈」,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News updateNews = new News();  

  2. updateNews.setTitle("今日iPhone6發佈");  

  3. updateNews.updateAll("title = ? and commentcount > ?""今日iPhone6發佈""0");  

仍是很是好理解的,這裏我就再也不詳細解釋了。

可是這種用法有一點須要注意,就是若是咱們想把某一條數據修改爲默認值,好比說將評論數修改爲0,只是調用updateNews.setCommentCount(0)這樣是不能修改爲功的,由於即便不調用這行代碼,commentCount的值也默認是0。因此若是想要將某一列的數據修改爲默認值的話,還須要藉助setToDefault()方法。用法也很簡單,在setToDefault()方法中傳入要修改的字段名就能夠了(類中的字段名),好比說咱們想要把news表中全部新聞的評論數清零,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News updateNews = new News();  

  2. updateNews.setToDefault("commentCount");  

  3. updateNews.updateAll();  

使用LitePal刪除數據

LitePal刪除數據的API和修改數據是比較相似的,可是更加的簡單一些,咱們先來看一下DataSupport類中的方法定義,以下所示:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public static int delete(Class<?> modelClass, long id)  

delete()方法接收兩個參數,第一個參數是Class,傳入咱們要刪除的那個類的Class就好,第二個參數是一個指定的id,表示咱們要刪除哪一行數據。

那麼好比說咱們想刪除news表中id爲2的記錄,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. DataSupport.delete(News.class2);  

須要注意的是,這不只僅會將news表中id爲2的記錄刪除,同時還會將其它表中以news id爲2的這條記錄做爲外鍵的數據一塊兒刪除掉,由於外鍵既然不存在了,那麼這麼數據也就沒有保留的意義了。

提及來可能有點拗口,咱們仍是舉例看一下。好比news表中目前有兩條數據,以下圖所示:


而後comment表中也有兩條數據,以下圖所示:


其中comment表中兩條數據的外鍵都是2,指向的news表中id爲2的這條記錄。那麼下面咱們執行以下刪除語句:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. int deleteCount = DataSupport.delete(News.class2);  

  2. Log.d("TAG""delete count is " + deleteCount);  

其中delete()方法的返回值表示被刪除的記錄數,打印結果以下所示:


能夠看到,有三條記錄被刪除了,那咱們再到news表中查詢一下:


OK,只剩下一條記錄了,id爲2的那條記錄確實被刪除了。那麼再到comment表中看一下呢,以下圖所示:


數據全沒了!爲何呢?由於comment表中的兩條數據都是以news表中id爲2的數據做爲外鍵的,如今外鍵不存在了,那麼這兩條數據天然也沒有存在的意義了,所以被刪除的記錄數一共是3條。這樣是否是就好理解了不少呢?

除了刪除指定id的數據以外,DataSupport中也提供了一個經過where語句來批量刪除數據的方法,先看一下方法定義:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public static int deleteAll(Class<?> modelClass, String... conditions)  

看起來很眼熟吧?很是簡單,deleteAll()方法接收兩個參數,第一個參數是Class,傳入咱們要刪除的那個類的Class就好,第二個參數是一個conditions數組,用於指定刪除哪些行的約束條件,返回值表示這次刪除了多少行數據,用法和updateAll()方法是基本相同的。

那麼好比說咱們想把news表中標題爲「今日iPhone6發佈」且評論數等於0的全部新聞都刪除掉,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. DataSupport.deleteAll(News.class"title = ? and commentcount = ?""今日iPhone6發佈""0");  

而若是咱們想把news表中全部的數據所有刪除掉,就能夠這樣寫:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. DataSupport.deleteAll(News.class);  

在不指定約束條件的狀況下,deleteAll()方法就會刪除表中全部的數據了。

除了DataSupport類中提供的靜態刪除方法以外,還有一個刪除方法是做用於對象上的,即任何一個繼承自DataSupport類的實例均可以經過調用delete()這個實例方法來刪除數據。但前提是這個對象必定是要持久化以後的,一個非持久化的對象若是調用了delete()方法則不會產生任何效果。

好比說下面這種寫法:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News news = new News();  

  2. news.delete();  

這裏new出了一個News對象,這個對象明顯是沒有持久化的,那麼此時調用delete()方法則不會刪除任何數據。

但若是咱們以前將這個對象持久化過了,那麼再調用delete()方法就會把這個對象對應的數據刪除掉了,好比:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News news = new News();  

  2. news.setTitle("這是一條新聞標題");  

  3. news.setContent("這是一條新聞內容");  

  4. news.save();  

  5. ...  

  6. news.delete();  

一個對象若是save過了以後,那就是持久化的了。除了調用save()方法以外,經過DataSupport中提供的查詢方法從數據庫中查出來的對象也是通過持久化的,查詢的功能咱們會在下篇博客中講解。

另外還有一個簡單的辦法能夠幫助咱們判斷一個對象是不是持久化以後的,DataSupport類中提供了一個isSaved()方法,這個方法返回true就表示該對象是通過持久化的,返回false則表示該對象未通過持久化。那麼刪除一個對象對應的數據也就能夠這樣寫了:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. News news;  

  2. ...  

  3. if (news.isSaved()) {  

  4.     news.delete();  

  5. }  

好了,這樣咱們就把LitePal中提供的修改和刪除數據操做的用法基本都學習完了,那麼今天的文章就到這裏,下一篇文章中會開始講解查詢數據的用法,感興趣的朋友請繼續閱讀 Android數據庫高手祕籍(七)——體驗LitePal的查詢藝術 。

LitePal開源項目地址:https://github.com/LitePalFramework/LitePal

相關文章
相關標籤/搜索