Android數據庫高手祕籍(五)——LitePal的存儲操作

使用LitePal存儲數據

LitePal中與存儲相關的API其實並不多,但用法還是頗爲豐富的,而且比起傳統的insert()方法,使用LitePal來存儲數據可以簡單到讓你驚歎的地步,那麼今天我們就來完整地學習一下LitePal存儲數據的所有用法。

在前面幾篇文章當中,我們在項目裏已經建好了News、Comment、Introduction、Category這幾個實體類,通過這些實體類,LitePal就可以把相應的表自動創建出來。現在來觀察這幾個實體類,我們發現這幾個類都是沒有繼承結構的。沒錯,因爲LitePal進行表管理操作時不需要這些實體類有任何的繼承結構,當時爲了簡單起見就沒有寫。但是進行CRUD操作時就不行了,LitePal要求所有的實體類都要繼承自DataSupport這個類,因此這裏我們就要把繼承結構給加上才行。修改News類的代碼,如下所示:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. public class News extends DataSupport{  
  2.       
  3.     ......  
  4.       
  5.     // 自動生成get、set方法  
  6. }  
可以看到,這裏只是讓News類繼承自了DataSupport,其它什麼都沒有改變。另外幾個Comment、Introduction、Category類也使用同樣的改法,這裏就不一一演示了。

繼承了DataSupport類之後,這些實體類就擁有了進行CRUD操作的能力,那麼比如想要存儲一條數據到news表當中,就可以這樣寫:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. News news = new News();  
  2. news.setTitle("這是一條新聞標題");  
  3. news.setContent("這是一條新聞內容");  
  4. news.setPublishDate(new Date());  
  5. news.save();  
怎麼樣?是不是非常簡單,不需要SQLiteDatabase,不需要ContentValues,不需要通過列名組裝數據,甚至不需要指定表名,只需要new出一個News對象,然後把要存儲的數據通過setter方法傳入,最後調用一下save()方法就好了,而這個save()方法自然就是從DataSupport類中繼承而來的了。

除此之外,save()方法還是有返回值的,我們可以根據返回值來判斷存儲是否成功,比如說這樣寫:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. if (news.save()) {  
  2.     Toast.makeText(context, "存儲成功", Toast.LENGTH_SHORT).show();  
  3. else {  
  4.     Toast.makeText(context, "存儲失敗", Toast.LENGTH_SHORT).show();  
  5. }  
可以看出,save()方法返回的是一個布爾值,用於表示存儲成功還是失敗,但同時也說明這個方法是不會拋出異常的。有些朋友希望如果存儲失敗的話就拋出異常,而不是返回一個false,那就可以使用saveThrows()方法來代替,如下所示:
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. News news = new News();  
  2. news.setTitle("這是一條新聞標題");  
  3. news.setContent("這是一條新聞內容");  
  4. news.setPublishDate(new Date());  
  5. news.saveThrows();  
使用saveThrows()方法來存儲數據,一旦存儲失敗就會拋出一個DataSupportException異常,我們可以通過對這個異常進行捕獲來處理存儲失敗的情況。

那有些細心的朋友可能已經注意到,使用的insert()方法來存儲數據時是有返回值的,返回的是插入行對應的id。但LitePal中的save()方法返回的是布爾值,那麼我們怎樣才能拿到存儲成功之後這條數據對應的id呢?對此,LitePal使用了一種非常巧妙的做法,還記得我們在每個實體類中都定義了一個id字段嗎?當調用save()方法或saveThrows()方法存儲成功之後,LitePal會自動將該條數據對應的id賦值到實體類的id字段上。讓我們來做個試驗吧,代碼如下所示:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. News news = new News();  
  2. news.setTitle("這是一條新聞標題");  
  3. news.setContent("這是一條新聞內容");  
  4. news.setPublishDate(new Date());  
  5. Log.d("TAG""news id is " + news.getId());  
  6. news.save();  
  7. Log.d("TAG""news id is " + news.getId());  
在save之前打印一下news的id,在save之後再打印一次,現在運行一下,打印結果如下所示:


OK,在save之前打印的id是0,說明此時id這個字段還沒有被賦值,在save之後打印的id是1,說明此時id已經被賦值了。那麼我們再到數據庫表中再查看一下這條記錄到底有沒有存儲成功吧,如下圖所示:


可以看到,這條新聞確實已經存儲成功了,並且對應的id正是1,和我們前面打印的結果是一致的。

不過LitePal的存儲功能顯示不僅僅只有這些用法,事實上,LitePal在存儲數據的時候默默幫我們做了很多的事情,比如多個實體類之間有關聯關係的話,我們不需要考慮在存儲數據的時候怎麼去建立數據與數據之間的關聯,因爲LitePal一切都幫我們做好了。

還是通過一個例子來看一下吧,Comment和News之間是多對一的關係,一條News中是可以包含多條評論的,因此我們就可以這樣寫:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. Comment comment1 = new Comment();  
  2. comment1.setContent("好評!");  
  3. comment1.setPublishDate(new Date());  
  4. comment1.save();  
  5. Comment comment2 = new Comment();  
  6. comment2.setContent("贊一個");  
  7. comment2.setPublishDate(new Date());  
  8. comment2.save();  
  9. News news = new News();  
  10. news.getCommentList().add(comment1);  
  11. news.getCommentList().add(comment2);  
  12. news.setTitle("第二條新聞標題");  
  13. news.setContent("第二條新聞內容");  
  14. news.setPublishDate(new Date());  
  15. news.setCommentCount(news.getCommentList().size());  
  16. news.save();  
可以看到,這裏先是存儲了一條comment1數據,然後存儲一條comment2數據,接着在存儲News之前先把剛纔的兩個Comment對象添加到了News的commentList列表當中,這樣就表示這兩條Comment是屬於這個News對象的,最後再把News存儲到數據庫中,這樣它們之間的關聯關係就會自動建立了。讓我們查看數據庫表檢查一下吧,首先看一下news表,如下所示:


OK,第二條新聞已經成功存儲到news表中了,這條新聞的id是2。那麼從哪裏可以看出來關聯關係呢?我們在上一篇文章中學過,多對一關聯的時候,外鍵是存放在多方的,因此關聯關係我們要到comment表中去查看,如下所示:


可以看到,兩條評論都已經成功存儲到comment表中了,並且這兩條評論的news_id都是2,說明它們是屬於第二條新聞的。怎麼樣,僅僅是在存儲數據之前建立好實體類之間的關係,再調用一下save()方法,那麼數據之間的關聯關係就會自動建立了,是不是非常簡單?上面的代碼只是多對一情況的一種用法,還有一對一和多對多的情況,其實用法都是差不多的,相信你已經能舉一反三了。

另外,LitePal對集合數據的存儲還專門提供了一個方法,比如說我們有一個News集合,那麼應該怎樣去存儲這個集合中的每條News呢?傳統情況下可以這樣寫:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. List<News> newsList;  
  2. ...  
  3. for (News news : newsList) {  
  4.     news.save();  
  5. }  
通過一個循環來遍歷出這個集合中的每一個News對象,然後逐個調用save()方法。這樣的寫法當然是可以的,但是效率會比較低,因爲調用save()方法的時候除了會執行存儲操作之外,還會去分析News類的關聯關係,那麼每次循環都去重新分析一遍關聯關係顯然是比較耗時的。因此,LitePal提供了一個saveAll()方法,專門用於存儲集合數據的,用法如下所示:
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. List<News> newsList;  
  2. ...  
  3. DataSupport.saveAll(newsList);  
saveAll()方法接收一個Collection集合參數,只要把待存儲的集合數據傳入即可。這個方法可以完成和上面一段代碼完全一樣的功能,但效率卻會高得多,而且寫法也更加簡單。

好了,這樣我們就把LitePal中提供的存儲操作的用法全部都學完了,那麼今天的文章就到這裏,下一篇文章當中會開始講解更新和刪除操作的用法。感興趣的朋友請繼續閱讀 Android數據庫高手祕籍(六)——LitePal的修改和刪除操作 。

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

第一時間獲得博客更新提醒,以及更多技術信息分享,歡迎關注我的微信公衆號,掃一掃下方二維碼或搜索微信號guolin_blog,即可關注。

發佈了22 篇原創文章 · 獲贊 9 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章