LitePal是一款开源的Android数据库框架,采用了对象关系映射(ORM)的模式,将平时开发常用的数据库(SQLite)的功能进行了封装,开发者无需编写SQL语句即可完成所有数据库有关的基本操作。更重要的是LitePal非常轻量级,jar包只有不到100k大小,非常易于管理,非常容易上手。目前LitePal的源码已在GitHub上开源,这是链接。注意:此篇博客基于LitePal3.0.0并使用Java编写开发。
方式一:下载jar
点击这里下载Jar包下载并导入依赖。
方式二:在你的项目(build.gradle)中加入依赖并同步项目。
dependencies {
implementation ‘org.litepal.android:java:3.0.0’
}
首先我们需要创建一个assets的文件夹,如图所示。新建aseets文件的具体步骤,请参见何时不少年的博客。
接下来我们需要一个xml配置文件:litepal.xml,注意:此文件名只能为litepal.xml,不能为其他文件名且必须在aseets中,否则LitePal会找不到配置文件。文件的配置如下:
数据库操作需要使用到Context,但是我们并不希望每次使用时都去传一此这个参数,那样的话数据库操作将会非常繁琐,所以LitePal只需要在AndroidManifest.xml中配置一下Application,这样就不用再多次传递Context了(真正一次配置,处处使用)。
但是如果你有你的程序,并且已经在此配置,不希望改动原有的配置,例如:
没有问题,LitePal依然可以使用,只需要在你的应用程序中调用:LitePal.initialize(context); 像这样:
package com.sin998.testlitepal;
import android.app.Application;
import org.litepal.LitePal;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
LitePal.initialize(this);
}
}
注意:请务必尽早调用此方法。可以在Application 的onCreate()方法中调用。并始终记得使用应用程序上下文作为参数。不要将任何activity或service实例用作参数,否则可能会发生内存泄漏。到此,LitePal的配置完毕。
根据对象关系映射模式的理念,每个表都要对应一个模型。简而言之,如果我们想创建出一张表,那么就要有一个与此表对应的模型类。这需要继承LitePalSupport类。
package com.sin998.testlitepal.bean;
import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
public class Student extends LitePalSupport {
/*
*注意:id字段可写可不写,因为不管你的实体类有没有这个字段,LitePal
*都会默认创建一个id字段(若实体类中有则不会创建),因为每个表都必须要
*一个主键,作为此表的索引,id字段即为索引。
*/
private int id;
private String pname;
private int psex;
private double pscore;
//getter和setter方法
}
LitePal还支持注解的使用,例如:
@Column(nullable = true)
private int id;
此注解表示为列设置可空约束(传入boolean)。除此之外还有以下三种注解:
@Column(ignore = false)
private String pname;
忽略将此字段映射到列(传入boolean)。
@Column(unique = false)
private int psex;
为列设置唯一约束。(传入boolean)。
@Column(defaultValue = "60.00")
private double pscore;
使用字符串类型为列设置默认值,不管列类型是什么(传入String)。
注意:注解的默认值为:
@Column(nullable = true)
@Column(ignore = false)
@Column(unique = false)
@Column(defaultValue = "")
接下来回到之前的配置文件litepal.xml,添加如下代码,新增映射关系:
注意:这里有一个技巧(我觉得应该算吧),只要按住ctrl并将鼠标移动到实体类上,点击能跳转到实体类即代表配置正确。例如:
下次操作数据库时将自动生成表。例如,你通过如下代码可以获取SQLiteDatabase:
SQLiteDatabase db = LitePal.getDatabase();
LitePal支持的映射数据类型一共有8种,分别是:
int、short、long、float、double、boolean、String、Date
现在LitePal将会自动生成如下SQL语句:
CREATE TABLE student(
id INT NOT NULL PRIMARY KEY auto_increment,
pname CHAR,
psex INT,
pscore DOUBLE
);
LitePal升级表格非常简单。只需要修改你的实体类:
package com.sin998.testlitepal.bean;
import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
public class Student extends LitePalSupport {
/*
*注意:id字段可写可不写,因为不管你的实体类有没有这个字段,LitePal
*都会默认创建一个id字段(若实体类中有则不会创建),因为每个表都必须要
*一个主键,作为此表的索引,id字段即为索引。
*/
private int id;
private String pname;
@Column(defaultValue = "60.00")
private double pscore;
//getter和setter方法
}
然后在litepal.xml中升级数据库版本号:
这些表将在你下次运行数据库的时候升级。pname列将会被删除,其他列将会保留,pscore列的默认值修改为"60.00"。
但是有些升级条件是LitePal无法处理的,升级表中的所有数据都将被清除:
注意上述会导致数据丢失的情况。
LitePal对于数据操作十分便捷。从LitePalSupport继承的每个模型将提供save()方法。若是没有使用LitePal,我们想向表中插入一条数据需要SQLiteDatabase、ContentValues,然后一条一条通过values.put("","");来组装数据,最后再通过db.inset()插入。整个过程十分繁琐,写代码体验极其不好。但是现在你只需要:
Student createStudent = new Student();
createStudent.setPname("sin998");
createStudent.setPsex(1);
createStudent.setPscore(60.00);
createStudent.save();
运行程序,点击三次插入,再查看数据库中的数据:
数据保存成功。
由于save()方法是有返回值的,true代表成功,false代表失败。
因此我们可以根据此方法改写代码以判断数据是否插入成功,例如:
Student createStudent = new Student();
createStudent.setPname("sin998");
createStudent.setPsex(1);
createStudent.setPscore(60.00);
createStudent.save();
if (createStudent.save()) {
Toast.makeText(this, "插入数据成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "插入数据失败", Toast.LENGTH_SHORT).show();
}
但如果你更希望在插入数据失败时直接抛出异常(这有益于我们快速定位问题所在),那么你可以使用saveThrows();来替代,例如:
createStudent.saveThrows();
一般情况上述方法运行在UI线程,如果你的UI线程十分繁忙,但现在又需要插入大量的数据,不能再进行耗时操作(会有crash风险),那么你可以使用异步来插入数据,例如:
createStudent.saveAsync().listen(new SaveCallback() {
@Override
public void onFinish(boolean success) {
//TODO:插入完成后的操作
}
});
注意:LitePal的所有(没错,就是所有)数据库操作都支持异步,都可以在异步之后调用listen方法以监听操作完成,为节省篇幅,下文只调用异步,监听需读者自己编写。
LitePal的更新数据也同样简单,LitePal提供两种更新方式。
方式一:如果你知道id,想根据id来更新指定的数据,其原理是先根据id把信息查询出来,然后在set值,最后再调用save();把原先的值覆盖掉:
//第二个参数就传要更新的id
Student updateStudentById= LitePal.find(Student.class,1);
updateStudentById.setPname("这是修改的名字");
updateStudentById.setPsex(0);
updateStudentById.setPscore(100.00);
if (updateStudentById.save()) {
Toast.makeText(this, "更新数据成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "更新数据失败", Toast.LENGTH_SHORT).show();
}
重新运行程序,更新数据,再次查看数据库。
数据更新数据成功。
如果你想直接new出实体类然后再根据id来更新数据:
Student updateStudentById = new Student();
updateStudentById.setPname("这是更新的数据:我是直接new的student类");
updateStudentById.update(1);
运行程序,更新数据,查看数据库:
同
数据更新成功。
同样的,LitePal在更新数据时会返回更新了几条数据:
通过这个方法你可以把打log出来或者记录到日志中,便于记录、维护和管理。
同样的,如果你需要异步更新数据,你可以:
updateStudentById.updateAsync(1);
方式二:如果你想根据条件来更新所有的满足条件的数据:
Student updateStudentByConditions = new Student();
updateStudentByConditions.setPscore(100.00);
updateStudentByConditions.updateAll("pname = ? and psex = ? ","sin998","1");
学过Mysql的朋友应该猜到了,这很像sql的where语法,是的,就是它。
第一个参数接收一个字符串,相当于sql中的where部分,其中"?“将会与依次与后面的参数对应(”?"起一个占位作用,相当于占位符)。注意:这里的字段是你实体类的字段。运行程序,更新数据,查看数据库:
数据更新成功。同样的,若是你想使用异步方式:
updateStudentByConditions.updateAllAsync("pname = ? and psex = ? ", "sin998", "1");
方式三:将数据更新成默认值:
为了演示效果,我把数据库升级,将pscore字段的默认值设置为60.00:
@Column(defaultValue = "60.00")
private double pscore;
添加更新数据代码:
Student updateStudentToDefault = new Student();
updateStudentToDefault.setToDefault("pscore");
updateStudentToDefault.updateAll("pname = ? and psex = ? ", "sin998", "1");
运行程序,更新数据,查看数据库:
哎,我们设置的默认值不是60吗?怎么更新成0了…反复检查代码也没问题。
想要把一个字段更新成默认值(默认值就是当你new了一下model类,其里面的变量就会有默认值,int是0,double和float是0.0,boolean是false,String是null等等)。修改代码,运行程序,打印日志(方法logdStuInfo(Student student)的功能是把传入student的信息打印出来):
从日志可以看出,module类一new出来的时候就LitePal就马上会给字段赋上默认值。
LitePal的更新数据操作与删除数据操作大同小异。
方式一:通过id来删除数据
LitePal.delete(Student.class,1);
方式二:根据约束删除
LitePal.deleteAll(Student.class,"pname = ?","sin998");
同样的,delete方法也有返回值,返回int,表示影响了几行(包括级联删除行),你同样可以得到这些信息:
并且delete也支持异步:
LitePal.deleteAsync(Student.class, 1);
LitePal.deleteAllAsync(Student.class,"pname = ?","sin998");
终于到了查询数据了,查询数据才是让人又爱又恨。但是LitePal同样强大,你甚至可以花式查询你所需要的数据。
方式一:根据id查询
Student student = LitePal.find(Student.class,1);
方式二:查询所有数据
List allStuList = LitePal.findAll(Student.class);
方式三:根据约束查询
List stuList = LitePal.where("pname = ?","sin998").order("id desc").find(Student.class);
除此之外,LitePal还提供了很多方法便于我们使用(这跟SQL语法很相似),请根据自己项目的实际需要选择合适的方法,想深入了解请查阅源码,这里不在赘述:
你可以在运行时创建任意数量的数据库。例如:
LitePalDB litePalDB = new LitePalDB("demo", 1);
litePalDB.addClassName(Student.class.getName());
LitePal.use(litePalDB);
注意:你需要先提前定义好实体类,在需要的地方创建,上面的语句会创建名为"demo"的数据库,里面的表映射于Student实体类,然后LitePal将当前操作的数据库切换为demo。
如果你想创建一个新数据库并且配置和litepal.xml相同:
LitePalDB litePalDB = LitePalDB.fromDefault("newdb");
LitePal.use(litePalDB);
切换回默认的数据库:
LitePal.useDefault();
删除数据库:
LitePal.deleteDatabase("test");
监听数据库创建/升级
LitePal.registerDatabaseListener(new DatabaseListener() {
@Override
public void onCreate() {
// fill some initial data
}
@Override
public void onUpgrade(int oldVersion, int newVersion) {
// upgrade data in db
}
});
LitePal:github官网
项目所有源码已托管到github,点击这里进入
编写不易,转载请注明文章出处,谢谢!