前言

当需要管理大量规范数据的时候,数据库是个好东西呀。Android是自带数据库的,叫SQLite,不过用起来太麻烦,需要繁杂的操作并且要自己写SQL语句。所以就会有很多合我们心意第三方库给予帮助,比如今天推荐的LitePal。
LitePal是一款开源的Android数据库框架,采用对象关系映射即ORM模式,封装了常用功能并且很轻量,非常易于使用。
虽然此框架的作者郭霖大佬已经在自己博客里写了相关教程,但由于其第一篇博客教程是在2014年发布的,其中一些内容到现在已经不同了,于是我对其进行整合与编排,“班门弄斧”一下。

教程

配置

添加依赖

build.gradle(Module)
1
2
3
4
5
dependencies {
...
//LitePal
implementation 'org.litepal.guolindev:core:3.2.3'
}

添加配置

在项目assets文件夹中创建名为litepal.xml,然后将以下内容写入其中。如果没有此文件夹请手动创建。

litepal.xml
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="test" />
<version value="1" />
<list>
</list>
<storage value="internal" />
</litepal>

这是唯一需要的配置文件,属性如下:

  • dbname配置数据库名称,需要以.db为后缀但如果没有会自动追加
  • version配置数据库版本,每次数据库结构等变动需将此值加一
  • list配置映射类,会自动将每个映射类创建对应表
  • storage配置数据库位置,internal指在可访问的内部存储数据库目录中、external指在主外部储存可访问持久目录中

配置Application

如果不想一直传递Context参数,可以在AndroidManifest.xml中配置LitePalApplication,例如:

AndroidManifest.xml
1
2
3
4
5
6
7
8
<manifest>
<application
...
android:name="org.litepal.LitePalApplication"
>
...
</application>
</manifest>

如果有独立Application,可以在自己的Application中调用初始化方法,例如:

Application.java
1
2
3
4
5
6
7
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
LitePal.initialize(this);
}
}

开始

创建表

假设需要创建一张记录成绩的表,比如StudentScore表,那就需要对应的StudentScore类,并且应该继承自LitePalSupport类,如下:

StudentScore.java
1
2
public class StudentScore extends LitePalSupport {
}

然后,表中每列就对应着表中的一个字段。比如此表中,需要记录姓名、成绩、时间,那么应该有如下类成员:

StudentScore.java
1
2
3
4
5
6
7
8
public class StudentScore extends LitePalSupport {
private int id;
private String name;
private int score;
private Date date;
//对应的set与get方法
...
}

其中id字段可不写,因为会自动生成并将其作为表的主键。
此框架映射规则很轻量,只要是声明的字段是支持的数据类型则都会自动映射且不需要额外配置。支持进行对象关系映射的数据类型如下:

  • int
  • short
  • long
  • float
  • double
  • boolean
  • String
  • Date

最后,需要将此表类配置到映射列表,即将此类的完整类名加入list配置中,例如:

litepal.xml
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="test" />
<version value="1" />
<list>
<mapping class="包名.StudentScore" />
</list>
<storage value="internal" />
</litepal>

这样就完成了,现在只要对数据库有任何操作,此表就会被自动创建。例如如下代码获取SQLiteDatabase时:

1
SQLiteDatabase db = LitePal.getDatabase();

更新表

首先要修改对应类,例如:

StudentScore.java
1
2
3
4
5
6
7
8
9
public class StudentScore extends LitePalSupport {
private int id;
@Column(unique = true, defaultValue = "Anonymous")
private String name;
private int score;
private Date date;
//对应的set与get方法
...
}

然后增加litepal.xml中的版本号即可,例如:

litepal.xml
1
2
3
4
...
<!-- <version value="1" /> -->
<version value="2" />
...

这些内容将会在下次操作数据库时进行更新。
以下是一些无法处理的更新情况,因此将会删除对应表中的所有数据,请一定要注意:

  • 添加一个字段且注解为unique = true
  • 修改一个字段的注解为unique = true
  • 修改一个字段的注解为nullable = false

插入记录

插入一条记录,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
StudentScore scoreTom = new StudentScore();
scoreTom.setName("Tom");
scoreTom.setScore(90);
scoreTom.setDate(new Date());
//通过返回值判断
if (scoreTom.save()) {
//成功
} else {
//失败
}
//通过错误时抛出异常
scoreTom.saveThrows();
//获取id字段,将在save()后被自动赋值
scoreTom.getId();

插入多条记录,例如:

1
2
3
4
5
6
7
List<StudentScore> scoreList = ...
//通过返回值判断
if (LitePal.saveAll(scoreList)) {
//成功
} else {
//失败,其中有一条失败就会全部失败
}

删除记录

1
2
3
4
5
6
//根据id
LitePal.delete(StudentScore.class, id);
//根据条件
LitePal.deleteAll(StudentScore.class, "score < ?" , "60");
//清空
LitePal.deleteAll(StudentScore.class)

更新记录

1
2
3
4
5
6
7
8
9
10
11
12
//根据id
StudentScore scoreTomUpdate1 = LitePal.find(StudentScore.class, id);
scoreTomUpdate1.setScore(95);
scoreTomUpdate1.save();
//通过继承LitePalSupport的方法
StudentScore scoreTomUpdate2 = new StudentScore();
scoreTomUpdate2.setScore(95);
scoreTomUpdate2.update(id);
//根据条件
StudentScore scoreTomUpdate3 = new StudentScore();
scoreTomUpdate2.setScore(95);
scoreTomUpdate3.updateAll("name = ?", "Tom");

查询记录

1
2
3
4
5
6
//单条记录
StudentScore scoreTomQuery1 = LitePal.find(StudentScore.class, id);
//所有记录
List<StudentScore> scoreTomQuery2 = LitePal.findAll(StudentScore.class);
//复杂查询
List<StudentScore> scoreTomQuery3 = LitePal.where("name = ? and score > ?", "Tom", "90").order("date").find(StudentScore.class);

监听数据库

1
2
3
4
5
6
7
8
9
LitePal.registerDatabaseListener(new DatabaseListener() {
@Override
public void onCreate() {
}

@Override
public void onUpgrade(int oldVersion, int newVersion) {
}
});

此方法应该在操作任何数据库之前调用,这样才能获得回调。

多数据库

此框架支持创建多个数据库,如下:

1
2
3
LitePalDB litePalDB = new LitePalDB("test2", 1);
litePalDB.addClassName(StudentScore.class.getName());
LitePal.use(litePalDB);

这将会创建一个带有StudentScore表的名为test2的数据库。

如果只是创建新数据库但配置与litepal.xml相同时,如下:

1
2
LitePalDB litePalDB = new LitePalDB("test2");
LitePal.use(litePalDB);

通过如下方式切换至默认数据库:

1
LitePal.useDefault();

通过如下方式删除任何数据库:

1
LitePal.deleteDatabase("test2");

事务

此框架支持事务的操作,事务中的所有操作将会一起提交或回滚。

1
2
3
4
5
6
7
8
LitePal.beginTransaction();
boolean result1 = // 操作数据1的结果
boolean result2 = // 操作数据2的结果
boolean result3 = // 操作数据3的结果
if (result1 && result2 && result3) {
LitePal.setTransactionSuccessful();
}
LitePal.endTransaction();

索引

如果要给一个字段添加索引,只需在该字段上方添加对应注解即可,例如:

StudentScore.java
1
2
3
4
5
6
7
8
9
public class StudentScore extends LitePalSupport {
private int id;
@Column(index = true)
private String name;
private int score;
private Date date;
//对应的set与get方法
...
}

请注意,在移动端数据库加索引也许不是个好想法。而如果你对索引已经非常熟悉并且完全清楚自己在做什么的时候,可以使用索引。

聚合函数

count()

此函数用于统计行数,例如:

1
2
3
4
//普通
int result = LitePal.count(StudentScore.class);
//条件
int result = LitePal.where("score = ?", "60").count(StudentScore.class);

sum()

此函数用于对结果求和,例如:

1
int result = LitePal.sum(StudentScore.class, "score", int.class);

average()

此函数用于统计平均数,例如:

1
double result = LitePal.average(StudentScore.class, "score");

max()

此函数用于计算最大值,例如:

1
int result = LitePal.max(StudentScore.class, "score", int.class);

minmin()

此函数用于计算最小值,例如:

1
int result = LitePal.min(StudentScore.class, "score", int.class);

参考资料