6.5 使用LitePal操作数据库
上一节我们学习了使用SQLiteDatabase来操作SQLite数据库的方法。
6.5.1 LitePal简介
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成数据库的各种操作。
6.5.2 配置LitePal
大多数的开源项目都会将版本提交到jcenter上,我们只需要再app/build.gradle文件中声明该开源库的引用就可以了。
eg:compile 'org.litepal.android:core:1.4.1'
//前面都是固定的,1.4.1是版本号,最新的版本号可在litepal主页上查看
//这样就是将LitePal陈宫引入到当前项目中了,接下来需要配置litepal.xml文件。
//右击app/src/main目录,new/Directory,创建一个assets目录,新建一个litepal.xml文件
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname> //指定数据库名
<version value="1"></version> //指定数据库版本号
<list>
</list>
</litepal>
//需要再配置一下LitePalApplication,修改AndroidMainActivity.xml中的代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.litepaltest">
<application
android:name='org.litepal.LitePalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
</application>
</manifest>
6.5.3 创建和升级数据库
LitePal采用的是对象关系映射(ORM)的模式
简单的说,我们使用的编程语言是面向对象语言,而使用的数据库则是关系型数据库,那么将面对对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射。
它赋予我们一个强大的功能,就是可以用面向对象的思维来操作数据库,而不用再和SQL语句打交道了。
//定义个Book类
public class Book {
private int id;
private String author;
private double price;
private int pages;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//接下来需要将Book类添加到映射模型列表当中,修改litepal.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname> //指定数据库名
<version value="1"></version> //指定数据库版本号
<list>
//声明我们要配置的映射模型类,注意一定要使用完整的类名
<mapping class="com.example.litepaltest.Book"></mapping>
</list>
</litepal>
//接下来需要进行任意一次数据库的操作,就会自动创建数据库
//修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layou.activity_main);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LitePal.getDatabase(); //一次最简单的数据库操作,只要点击一下按钮,数据库就自动创建完成了
}
});
}
}
注意:升级别简单,只需要修改好内容,然后将版本号加1即可。
6.5.4 使用LitePal添加数据
只需要创建模型类的实例,再将所有要存储的数据设置好,最后调用一下save方法就可以了
注意:LitePal进行表管理操作时不需要模型类有任何的继承结构,但是进行CRUD操作时就必须要继承DataSupport类才行
因此:public class Book extends DataSupport { ... }
//修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layou.activity_main);
...
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setName("ni"); //调用Book的set方法对数据进行设置
book.setAuthor("Lu");
book.setPages(545);
book.setPrice(15.22);
book.save(); //调用DataSupport中的save方法来进行完成添加数据的操作
}
});
}
}
6.5.5 使用Litepal更新数据
首先需要了解一个概念: 什么事已存储的对象?
对于Litepal来说,对象是否已存储就是根据调用model.isSaved()方法的结果来判断的,返回true表示已存储,返回false表示未存储。
如果已经调用过save方法则model会被认为是已存储对象。
如果model对象是通过LitePal提供的API查出来的,也会被认为是已存储的对象。
//修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layou.activity_main);
...
Button upData = (Button) findViewById(R.id.up_data);
upData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setName("ni"); //调用Book的set方法对数据进行设置
book.setAuthor("Lu");
book.setPages(545);
book.setPrice(15.22);
book.save(); //调用DataSupport中的save方法来进行完成添加数据的操作
book.setPrice(23.33); //重新设置价格
book.save(); //由于已经save过是已存储的,因此不添加新数据,直接更新当前数据
}
});
}
}
//上面那种更新方式只能对已存储的对象进行操作,限制性比较大,下面介绍一种新的
//修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layou.activity_main);
...
Button upDate = (Button) findViewById(R.id.up_date);
upDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setPrice(23.33); //重新设置价格
book.updateAll("name=? and author=?","ni","Lu");
//将书名为ni,作者为Lu的书本价格更新为23.33
}
});
}
}
注意:使用updateAll()方法时,当你想把一个字段的值更新成默认值,LitePal提供了一个setToDefault方法,然后传入相应的列就可以实现将数据更新成默认值了。
eg:Book book = new Book();
book.setToDefault("pages");book.updateAll();
updateAll没有约束条件,因此更新操作对所有数据都生效了
6.5.6 使用LitePal删除数据
使用LitePal删除数据的方式主要有两种,第一种比较简单,就是直接调用已存储的对象delete()就可以。
//另一种删除数据的方式
DataSupport.deleteAll(Book.class,"price<?","15"); //删除Book表中价格低于15的书//使用DataSupport的deleteAll方法,这个方法如果不指定约束,则表示删除表中所有数据
6.5.7 使用litePal查询数据
List<Book> books = DataSupport.findAll(Book.class);
注意:这个方法返回的是一个Book类型的List集合
//修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layou.activity_main);
...
Button upDate = (Button) findViewById(R.id.up_date);
upDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<Book> books = DataSupport.findAll(Book.class);
for (Book book: books) {
Log.d("MainActivity",book.getName());
...
}
}
});
}
}
注意:除了findAll()方法外,LitePal还提供了很多其他非常有用的查询API
1.查询Book表中的第一条数据
Book firstBook = DataSupport.findFirst(Book.class);2.查询Book表中的最后一条数据
Book lastBook = DataSupport.findLast(Book.class);
还可以通过连缀查询来定制更多的查询功能
1.select方法,查name和author这两列的数据
List<Book> books = DataSupport.select("name","author").find(Book.class);2.where方法,查页数大于400的数据
List<Book> books = DataSupport.where("pages > ?","400").find(Book.class);
3.order方法,将查询结果按价格从高到低排序
List<Book> books = DataSupport.order("price desc").find(Book.class);
desc:降序排列 asc:升序排列
4.limit方法,只查前三条List<Book> books = DataSupport.limit("3").find(Book.class);
5.offset方法,偏移量,只查234条
List<Book> books = DataSupport.limit("3").offset(1).find(Book.class);
还可以对上面5个组合:
List<Book> books = DataSupport.select("name","author","pages").where("pages > ?","400")
.order("pages")
.limit("3")
.offset(10)
.find(Book.class);
这段代码表示:查询Book表中第11-20条满足页数大于400这个条件的name,author,pages这三列数据,并将查询结果按照页数升序排列。
排序默认升序
最后:LitePal也支持原生的SQL来进行查询
Cursor c = DataSupport.findBySQL("select * from Book where pages > ? and price < ?","400","20");
//这里返回的还是一个cursor对象,因此数据也需要使用cursor.getXxx(cursor.getColumnindex("xxx"));来取出