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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章