LitePal總結

對Litepal總結的修改

1、配置LitePal

  1. 導入LitePal的jar

    dependencies {
        ...
        compile 'org.litepal.android:core:1.4.0'
        ...
    }
  2. 創建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> 
  3. 配置Application,在項目中引用LitePalApplication或是創建自己的Application繼承LitePalApplication.

2、建表

  1. 創建表所需要的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方法
    ...
    }
  2. 在數據庫配置文件中配置表

    <?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

非法屬性引發的異常,列出常見異常:

  1. dbname is empty or not defined in litepal.xml file。
    根據理解,是數據庫不存在或是字段名錯誤。
    出現此種情況的可能:

    • 在Litepal數據庫創建之前就調用了聚集函數,比如Count,max等,在源碼中能夠找到DataSupport.count(xxx.class)的過程中沒有走創建數據庫的過程,所以報bdname is empty的問題。
發佈了37 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章