【Android】18.0 SQLite資料庫——LitePal的使用及SQLite資料庫怎麼檢視
1.0 自己用的郭霖先生的《第一行程式碼》第二版,但是隨著android程式設計的更新,書中不少內容出現失效、棄用現象。寫這個同時也是給自己做筆記。
2.0 Android系統內建資料庫,SQLite輕量級的關係型資料庫,當然,使用起來其實很麻煩,還需要熟練使用SQL語句。
3.0 開源讓Android開發者收益良多,導致GitHub上有成百上千的優秀Android開源專案,使用當我們使用開源庫LitePal時,將會特別感受到SQLite資料庫使用的容易性。
4.0 LitePal專案主頁當然有詳細的使用文件,地址是: GitHub - LitePalFramework/LitePal: 一個Android庫,使開發人員非常容易使用sqlite資料庫
5.0 配置LitePal。
編輯app/build.gradle檔案,在dependencies閉包中新增如下內容:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' implementation 'org.litepal.android:java:3.0.0' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }
新增這行程式碼中,“org.litepal.android:java:”是固定的,後面的版本號可以去 LitePal專案主頁上檢視。
6.0 新建一個專案,我的目錄結構如下:

2019-02-18_212302.png
當然這裡也不要忘了,更新下程式設計環境,點這個:

2019-02-18_212628.png
7.0 litepal.xml內容如下:
<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="BookStore"></dbname> <version value="2"></version> <list> <mapping class="com.example.litepaltest.Book"></mapping> <mapping class="com.example.litepaltest.Category"></mapping> </list> </litepal>
dbname 標籤用於指定資料庫名
version 標籤用於指定資料庫版本號,這裡我因為已經玩了幾輪了,已經更新到2。
mapping 標籤裡面都是全路徑名稱下的具體的表。
8.0 最後還需要配置下LitePalApplication,修改AndroidManifest.xml中的程式碼,如下所示:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.litepaltest"> <application android:name="org.litepal.LitePalApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
主要是application標籤下增加android:name="org.litepal.LitePalApplication",其他都是自動生成的。
這樣LitePal的所有功能都能正常工作了,LitePal配置工作完全結束。
9.0 LitePal最大的好處,就在於她是相當於面向物件的,嚴肅的說,叫做採用的是物件關係對映(ORM)的模式。
這樣可以用面向物件的思維來操作資料庫,而不用再和SQL語句打交道,並且可以直接指定好了資料的資料型別。
例如在這個專案中,再定義一個Book類,程式碼如下:
package com.example.litepaltest; import org.litepal.crud.LitePalSupport; public class Book extends LitePalSupport { private int id; private String author; private double price; private int pages; private String name; private String press; public String getPress() { return press; } public void setPress(String press) { this.press = press; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getPages() { return pages; } public void setPages(int pages) { this.pages = pages; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
可見這是一個典型的Java bean。相當於對應資料庫中的Book表。
10.0 由於前面已經描述了litepal.xml中的程式碼,事實上,坐好Book類,還需要在這個檔案中用mapping標籤來宣告要配置的對映模型類。這裡就不再貼程式碼了。
11.0修改MainActivity.java中的程式碼,建立資料庫:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button createDatebase = (Button) findViewById(R.id.create_database); createDatebase.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LitePal.getDatabase(); } });
這裡用了LitePal.getDatabase();建立資料庫,執行,可以點選那個Button控制元件(最後一次性貼activity_main.xml的程式碼,裡面到時候會配置4個按鈕控制元件),資料庫建立成功。
12.0 怎麼可以檢視資料庫是否真的建立好了,在我的參考書裡面是通過adb.exe,在命令視窗,通過命令列檢視,但是Android6.0以後的版本的模擬器,這個方法根本進不去資料庫。
所以我用的第二種方法。
12.1 首先你得裝一個Navicat Premium,資料庫視覺化軟體。
我的是Navicat Premium 12。
12.2 然後執行專案後,點選按鈕,建立資料庫。然後開啟Android studio,在右下角可以看到Device File Explorer,接下來的操作如圖所示:

2019-02-19_152423.png

2019-02-19_152804.png

2019-02-19_153356.png
當然,如果你找不到Device File Explorer,可以到View→Tool Windows→Device File Explorer:

2019-02-19_153021.png
如果這樣都沒有的話,那就涼涼了……
12.3 接下來開啟Navicat Premium ,點選SQLite,操作如圖:

2019-02-19_153637.png
選擇資料庫檔案,

2019-02-19_153711.png
找到儲存的目錄,選擇目錄檔案,開啟

2019-02-19_153844.png

2019-02-19_154119.png
這樣,就可以檢視到相關的內容了(我的因為多寫了別的程式碼,導致裡面有資料)

2019-02-19_154310.png
13.0 常說的增刪查改。首先是想新增一個出版社,直接修改Book程式碼,新增一個press欄位即可,上面的程式碼,已經是新增完畢的。
14.0 如果還想再新增一張Category表,那麼只需要新增一個Category類即可:
Category.java
package com.example.litepaltest; public class Category { private int id; private String categoryName; private int categoryCode; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCategoryName() { return categoryName; } public void setCategoryName(String categoryName) { this.categoryName = categoryName; } public int getCategoryCode() { return categoryCode; } public void setCategoryCode(int categoryCode) { this.categoryCode = categoryCode; } }
但別忘了在litepal.xml中增加一個mapping(在上面貼的完整程式碼中已新增好):
<mapping class="com.example.litepaltest.Category"></mapping>
15.0 新增資料,LitePal進行表管理操作時不需要模型類有任何的繼承結構,但是進行CRUD操作時就不行,必須繼承LitePalSupport類才行(之前是繼承DataSupport類,現在已經被棄用)
上面可以看到我們的Book類已經被我加上了繼承結構,但在建立表時,可以不用該繼承。
新增資料,將資料設定好,呼叫下save()方法即可,只需要修改下MainActivity.java中的程式碼(當然,這裡又增加了一個Button按鈕):
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button addData = (Button) findViewById(R.id.add_data); addData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Book book = new Book(); book.setName("中國古代歷史"); book.setAuthor("睡醒著"); book.setPages(454); book.setPrice(16.96); book.setPress("Unknow"); book.save(); } }); } }
16.0更新資料,如下:
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button updateData = (Button) findViewById(R.id.update_data); updateData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Book book = new Book(); book.setName("大亨小傳"); book.setAuthor("java著"); book.setPages(329); book.setPrice(21.96); book.setPress("Unknow"); book.save(); book.setPrice(51.96); book.save(); } }); } }
當然,還可以更加靈巧的更新資料:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button updateData = (Button) findViewById(R.id.update_data); updateData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Book book = new Book(); book.setPrice(33.96); book.setPress("Anchor"); book.updateAll("name= ? and author = ?","中國古代歷史","睡醒著"); } }); } }
上面updateAll()方法的意思是匹配Book表中,所有名字叫“中國古代歷史“”,而且作者是“睡醒著”的所有資料,將他們的價格和出版社給改了。
還可以將某個資料恢復成系統預設值:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button updateData = (Button) findViewById(R.id.update_data); updateData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //下面三句程式碼的意思是:把所有書的頁數設定為預設值0 Book book = new Book(); book.setToDefault("pages"); book.updateAll(); } }); } }
17.0 刪除資料,如下:
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button deleteData = (Button) findViewById(R.id.delete_data); deleteData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //這裡之前的DataSupport被棄用,取而代之的是LitePal LitePal.deleteAll(Book.class,"price < ?","23"); } }); } }
上句話的意思是,刪除Book表中所有價格小於23的書的資料。
18.0 查詢資料,很簡單:
在Button控制元件監控的基礎上,直接增加如下程式碼:
18.1 查詢Book表中的所有資料:
List<Book> book = LitePal.findAll(Book.class);
18.2 查詢Book表中的第一條資料:
Book firstBook = LitePal.findFirst(Book.class);
18.3 查詢Book表中的最後一條資料:
Book lastBook = LitePal.findLast(Book.class);
18.4 只查詢Book表中的name和author這兩列資料(對應SQL中的select關鍵字):
List<Book> book = LitePal.select("name","author").find(Book.class);
18.5 只查詢Book表中的頁數大於400的資料(對應SQL中的where關鍵字):
List<Book> book = LitePal.where("pages > ?","400").find(Book.class);
18.6 查詢Book表,將查詢結果按照書價從高到低排序(對應SQL中的order by關鍵字):
List<Book> book = LitePal.order("price desc ").find(Book.class);
其中“desc”表示降序排序,不寫或者"asc"表示升序排序
18.7 查詢Book表中的前3條資料:
List<Book> book = LitePal.limit(3).find(Book.class);
18.8 查詢Book表中的第2條、第3條、第4條資料:
List<Book> book = LitePal.limit(3).offset(1).find(Book.class);
limit(3)查詢的是前3條資料(第1、2、3條),再加一個offset(1)進行位置的偏移,意味著查詢第2、3、4條資料了,這兩個方法相結合對應SQL語句中的limit關鍵字。
18.9 劃重點 的來了,可以把select()、where()、order()、limit()、offset()五個方法任意組合,以完成一個複雜的查詢操作,比如查詢Book表中第11-20條滿足頁數大於400這個條件的name、author和pages這3列資料,並將查詢結果按照頁數的升序排列:
List<Book> book = LitePal.selcect("name","author","pages") .where("pages > ?","400") .order(pages) .limit(10) .offset(10) .find(Book.class);
18.10 最後,如果LitePal這都滿足不了你窮凶極惡的需求,name它仍然支援使用原生的SQL來查詢:
Cursor c = LitePal.findBySQL("select * from Book where pages > ? and price < ?","400","20");
當然,這樣資料需要取出來的話,就得通過Cursor的各種get方法了。