1、配置LitePal
導入LitePal的jar
dependencies { ... compile 'org.litepal.android:core:1.4.0' ... }
創建assets文件夾,並在文件夾下創建litepal.xml文件,此文件作爲LitePal的配置文件。
litepal.xml的具體內容如下,其中bdname的Value爲數據庫名;version爲數據庫版本;表情中是需要創建的表名。
<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="Teemo.db" ></dbname> <version value="1" ></version> <list> </list> </litepal>
- 配置Application,在項目中引用LitePalApplication或是創建自己的Application繼承LitePalApplication.
2、建表
創建表所需要的Model
一張表對應一個模型(Model),例如:想創建一張User表,則有:
package com.teemo.example.database.model; public class User extends org.litepal.crud.DataSupport { ... }
表中的每個字段對應模型中的每個屬性。例如:在User表中添加userName、id字段,則需要在User類中添加userName、id屬性,兩者是一一對應的。
package com.teemo.example.database.model; public class User extends org.litepal.crud.DataSupport { private int id; private String name; //自動生成get、set方法 ... }
在數據庫配置文件中配置表
<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="Teemo.db" ></dbname> <version value="1" ></version> <list> <mapping class="com.teemo.example.database.model.User"/> </list> </litepal>
根據LitePal的數據類型支持,可以進行對象關係映射的數據類型一共有8種,int、short、long、float、double、boolean、String和Date。只要是聲明成這8種數據類型的字段都會被自動映射到數據庫表中,並不需要進行任何額外的配置。
3、使用LitePal升級數據庫
添加新表 MessageInfo
創建MessageInfo的Model類:package com.teemo.example.database.model; public class MessageInfo extends org.litepal.crud.DataSupport { private int id; private String userName; private String msgContent; //自動生成get、set方法 ... }
將MessageInfo配置到數據庫配置文件中,並新增數據庫版本號
<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="Teemo.db" ></dbname> <version value="2" ></version> <list> <mapping class="com.teemo.example.database.model.User"/> <mapping class="com.teemo.example.database.model.MessageInfo"/> </list> </litepal>
修改表中的字段:
修改表中的字段只需要修改Model中的屬性,並將數據庫的版本號加1即可,例如:在MessageInfo表中添加字段senderNumber。package com.teemo.example.database.model; public class MessageInfo extends org.litepal.crud.DataSupport { private int id; private String userName; private String msgContent; private String senderNumber; //自動生成get、set方法 ... }
<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="Teemo.db" ></dbname> <version value="3" ></version> <list> <mapping class="com.teemo.example.database.model.User"/> <mapping class="com.teemo.example.database.model.MessageInfo"/> </list> </litepal>
注: SQLite中是不支持表刪除字段的,不過在LitePal中可以做到,原理是先將表重命名爲temp表,然後根據新的配置文件創建新表,再將temp表中的數據移到新表中,同時刪除temp表。
4、使用LitePal創建關聯表
>創建關聯表:一對一關聯的實現方式是用外鍵,多對一關聯的實現方式同樣是外鍵,多對多關聯的實現方式是用中間表。
創建一對多表,一個User會有多條MessageInfo,所以User和MessageInfo是多對一的形式;可以對上述User、MessageInfo類做如下修改:
package com.teemo.example.database.model; public class User extends org.litepal.crud.DataSupport { private List<MessageInfo> msgInfoList = new ArrayList<MessageInfo>(); //自動生成get、set方法 ... }
package com.teemo.example.database.model; public class MessageInfo extends org.litepal.crud.DataSupport { private User user; //自動生成get、set方法 ... }
爲了實現多對多的關係,建立Market表,一個Market可以在多個MessageInfo中出現,一個MessageInfo中可以包含多個Market,那麼Market和MessageInfo就是多對多的方式。
package com.teemo.example.database.model; public class Market extends org.litepal.crud.DataSupport { private List<MessageInfo> msgInfoList = new ArrayList<MessageInfo>(); //自動生成get、set方法 ... }
package com.teemo.example.database.model; public class MessageInfo extends org.litepal.crud.DataSupport { private User user; private List<Market> msgInfoList = new ArrayList<Market>(); //自動生成get、set方法 ... }
此時Market表和MessageInfo表就是多對多的關係。
5、使用LitePal進行插入數據:
litepal插入數據時需要Model繼承了DataSupport接口才能使用LitePal的CRUD操作。
例如想插入一條User數據:
java
User user = new User();
user.setName("Teemo");
user.save();
save()方法有返回值,能夠表明插入操作是否成:
```java
if(user.save())
Toast.show(context, "存儲成功", Toast.LENGTH_SHORT).show();
else
Toast.show(context, "存儲失敗", Toast.LENGTH_SHORT).show();
```
同時可以採用user.saveThrows();來爲插入失敗時拋出異常。和SQLite的Insert方法一樣,save()同樣可以得到返回的ID
```java
User user = new User();
user.setName();
Log.d(TAG, "user's id is " + user.getId());
user.sava();
Log.d(TAG, "user's id is " + user.getId());
```
如果想在User表中插入多條MessageInfo,可以如下所示:
```java
MessageInfo msgInfo1 = new MessageInfo();
msgInfo1.setUserName("Tom");
msgInfo1.serMsgContent("Hello Tom");
msgInfo.save();
MessageInfo msgInfo2 = new MessageInfo();
msgInfo2.setUserName("Peter");
msgInfo2.setMsgContent("Hello Peter");
msgInfo2.save();
User user = new User();
user.getMsgInfoList().add(msgInfo1);
user.getMsgInfoList().add(msgInfo2);
user.setName("Teemo");
user.save();
```
如果想插入一個User集合,可以有:
List<News> newsList; ... DataSupport.saveAll(newsList);
6、使用LitePal修改數據
比如我們想將User表中的id爲1的記錄的名稱改爲Tom:
```java
ContentValues values = new ContentValues();
values.put("name", "Tom");
DataSupport.update(User.class, values, 1);
```
如果想修改某條件下所有的數據,而不是單指的id,則可以使用如下的命令:
```java
DataSupport.updateAll(Class<?> modelClass, ContentValues values, String conditions)
```
第三個參數是一個conditions數組,用於指定修改哪些行的約束條件,返回值表示此次修改影響了多少行數據。
比如我們想將User表中所有叫Teemo的name換成Tom,則有:
```java
ContentValues value = new ContentValues();
value.put("name", "Tom");
DataSupport.updateAll(User.class, value, "name = ?", "Toom");
```
其中”Teemo”代表?佔位符,一個佔位符需要一個字符串對應。
如果我們想將User中所有項的name換成Tom,則有:
```java
ContentValues value = new ContentValues();
value.put("name", "Tom");
DataSupport.updateAll(User.class, value);
```
如果想將User中的name換成默認名,則有:
```java
ContentValues value = new ContentValues();
value.setToDefault("name");
DataSupport.updateAll();
```
7、使用LitePal刪除表中的某一項
具體方法如下:
```java
public static int delete(Class<?> modelClass, long id);
```
比如說想刪除User的第一項:
```java
DataSupport.delete(User.class, 1);
```
需要注意的是,這不僅僅會將User表中id爲1的記錄刪除了,同時還會降其他表中以User id爲1的這條記錄作爲外鍵的數據一起刪掉,因爲外鍵既然不存在了,那麼這數據也就沒有保留的必要。
除了刪除制定id的數據之外,DataSupport中也提供了一個通過Where語句來批量刪除數據的方法:
```java
public static int deleteAll(Class<?> modelClass, String... conditions);
```
比如想將User中name爲Teemo的刪掉,則可這樣寫:
```java
DataSupport.deleteAll(User.class, "name = ?", "Teemo");
```
如果想將User中所有記錄刪除,則可有:
```java
DataSupport.deleteAll(User.class);
```
8、使用Litepal查找數據:
比如想查詢User的第一條記錄:
```java
User user = DataSupport.find(User.class, 1);
```
同時,LitePal還支持findFirst、findLast操作,使用方法和find同樣。
如果我們想找第1、3、5項記錄:
```java
List<User> users = DataSupport.findAll(User.class, 1, 3, 5);
```
也可以
```java
long ids[] = new long[] {1, 3, 5};
List<User> users = DataSupport.findAll(User.class, ids);
```
連綴查詢
如果我們想查詢所有id > 5的記錄:List<User> userList = DataSupport.where("id > ?", "5").find(User.class);
這樣我們將User中所有字段都查找出來了,如果我們只想要User中的name屬性,則可以有:
```java
List<User> userList = DataSupport.select("name")
.where("id > ?", "5")
.find(User.class);
```
如果我們想將查詢的數據按照id的大小進行排名,則可以有:
```java
List<User> userList = DataSupport.select("name")
.where("id > ?", "5")
.order("id desc")
.find(User.class);
```
在表中可能存在很多的User,我們並不想將其全部查出來,只想找出前面的10項,則有:
```java
List<User> userList = DataSupport.select("name")
.where("id > ?", "5")
.order("id desc")
.limit(10)
.find(User.class);
```
上面我們查詢的是所有匹配條件的前10條數據,現在我們想將User進行分頁展示,翻到第二頁時,展示第11到20的User,則有:
```java
List<User> userList = DataSupport.select("name")
.where("id > ?", "5")
.order("id desc")
.limit(10)
.offset(10)
.find(User.class);
```
- 激進查詢:
激進查詢能夠將表中關聯的數據一起查找出來
在每個find方法中都有一個帶isEager的重構方法,使用這種方法時,並傳入true就代表激進查詢。但是激進查詢在LitePal中不推薦。
不推薦那麼可以對錶進行稍微修改就可以做到:
```java
package com.teemo.example.database.model:
public class User extends org.litepal.DataSupport {
private List<MessageInfo> msgInfos;
public List<MessageInfo> getMsgInfos() {
return DataSupport.where("user_id = ?", String.valueOf(id)).find(MessageInfo.class);
}
}
```
9、Litepal的聚合函數
LitePal中一共提供了count()、sum()、average()、max()和min()這五種聚合函數,基本上已經將SQL語句當中最常用的幾種聚合函數都覆蓋了
- Count()
如果想統計User表中有多少記錄:
```java
int count = DataSupport.count(User.class);
```
聚合函數還支持連綴,也就是說我們在進行統計的時候還可以加入條件語句:
```java
int count = DataSupport.where("name = ?", "Teemo").count(User.class);
```
- Sum()
sum()方法主要是用於對結果進行求合的,比如說我們想要統計User表中Message的總數量,就可以這樣寫:
```java
int sum = DataSupport.sum(User.class, "msgCount", int.class);
```
sum()方法的參數要稍微多一點,我們來一一看下。第一個參數很簡單,還是傳入的Class,用於指定去統計哪張表當中的數據。第二個參數是列名,表示我們希望對哪一個列中的數據進行求合。第三個參數用於指定結果的類型,這裏我們指定成int型,因此返回結果也是int型。
需要注意的是,sum()方法只能對具有運算能力的列進行求合,比如說整型列或者浮點型列,如果你傳入一個字符串類型的列去求合,肯定是得不到任何結果的,這時只會返回一個0作爲結果。
- average()
average()方法主要是用於統計平均數的,比如說我們想要統計User表中平均每個人有多少信息,就可以這樣寫:
```java
double result = DataSupport.average(User.class, "msgCount");
```
同樣地,average()方法也只能對具有運算能力的列進行求平均值,如果你傳入了一個字符串類型的列,也是無法得到任何結果的,這時同樣只會返回一個0作爲結果。
- max()
max()方法主要用於求出某個列中最大的數值,比如我們想要知道User表中所有人中消息最多的是多少,就可以這樣寫:
```java
int max = DataSupport.max(User.class, "msgCount", int.class);
```
- min()
min()方法主要用於求出某個列中最小的數值,比如我們想要知道User表中所有人中消息最少的是多少,就可以這樣寫:
```java
int min = DataSupport.min(User.class, "msgCount", int.class);
```
10、錯誤總結
InvalidAttributesException
非法屬性引發的異常,列出常見異常:
dbname is empty or not defined in litepal.xml file。
根據理解,是數據庫不存在或是字段名錯誤。
出現此種情況的可能:- 在Litepal數據庫創建之前就調用了聚集函數,比如Count,max等,在源碼中能夠找到DataSupport.count(xxx.class)的過程中沒有走創建數據庫的過程,所以報bdname is empty的問題。