参考书籍:Android第一行代码(第二版).郭霖著
LitePal是一款开源的Android数据库框架,采用对象关系映射(ORM)模式,将开发常用的数据库功能进行封装,不用编写SQL语句就可完成各种建表增删查改操作。项目主页上有详细使用文档:https://github.com/LitePalFramework/LitePal
1、配置LitePal(Android Studio)
现在大多数的开源项目都会提交到jcenter上,所以只需在app/build.gradle文件中声明该开源库的引用就可以了:
compile ‘org.litepal.android:core:1.5.1’
前面部分固定,1.5.1为版本号(最新的去LitePal项目主页上查看)。
接下来需配置litepal.xml文件。右键app/src/main目录->New->Directory,创建一个assets目录,在其中新建一个litepal.xml文件,编辑其中内容:
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore" />
<version value="1" />
<list>
</list>
</litepal>
指定数据库名、数据库版本号,指定所有映射模型。
最后需配置LitePalApplication,修改AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.jojo.litepaltest">
<application
**android:name="org.litepal.LitePalApplication"**
android:allowBackup="true"
。。。
将项目的application配置为org.litepal.LitePalApplication,才能让LitePal的所有功能正常工作。
2、创建升级数据库
实现与DatabaseTest同样的功能。先将activity_main.xml文件从DatabaseTest项目复制过来。
对象关系映射:将面向对象的语言(我们使用的编程语言)和面向关系的数据库(关系型数据库)之间建立一种映射关系。此模式可以让我们用面向对象的思维操作数据库,不用和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 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 getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
典型的JavaBean(一段特殊的Java类:有无参构造方法,只有get、set方法的Java类对象)。Book类对应Book表,类中每个字段对应表中每个列(对象关系映射)。
需将Book类添加到映射模型列表中,修改litepal.xml:
<litepal>
<dbname value="BookStore" />
<version value="1" />
<list>
<mapping class="com.example.jojo.litepaltest.Book"/>
</list>
</litepal>
声明配置的映射模型类,使用完整类名。
所有工作完成,只要进行任意一次数据库操作,BookStore.db数据库就会自动创建出来。修改MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Connector.getDatabase();
}
});
}
}
运行程序,点击创建按钮,通过adb shell查看情况。
打开数据库,通过.schema查看建表语句,有三张表的建表语句,前两张都是内部表不用管。
之前使用SQLiteOpenHelper升级数据库,需要把之前的表drop掉再重新创建(造成数据丢失,升级一次,之前表中数据全丢),可通过复杂逻辑控制避免此问题但维护成本很高。使用LitePal只需修改想改的内容,将版本号加1即可。
如向Book中添加press(出版社)心裂,直接修改该Book类,添加press字段及相应get\set方法即可。同时添加一张Category表,只需创建此类即可:
public class Category {
private int id;
private String categoryName;
private int categoryCode;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setCategoryCode(int categoryCode) {
this.categoryCode = categoryCode;
}
public int getCategoryCode() {
return categoryCode;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryName() {
return categoryName;
}
}
将其添加到映射模型列表中,将版本号加1:
<litepal>
<dbname value="BookStore" />
<version value="2" />
<list>
<mapping class="com.example.jojo.litepaltest.Book"/>
<mapping class="com.example.jojo.litepaltest.Category"/>
</list>
</litepal>
重新运行程序,点击创建按钮,查看建表语句:
LitePal会自动保留之前表中的所有数据。
3、添加数据
只需创建出模型类实例,将所有要存储的数据设置好,最后调用一下save()方法就可以了。
现有模型类都没有继承结构(LitePal进行表管理操作时不需要模型类有任何继承结构),但进行CRUD操作必须要继承自DataSupport类才行,所以需给现有类加上此继承:
public class Book extends DataSupport{
向Book中添加数据,修改主程序:
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("The Da Vinci Code");
book.setAuthor("Dan Brown");
book.setPages(454);
book.setPrice(16.96);
book.setPress("Unknow");
book.save();//从DataSupport类中继承的方法,其中提供了丰富的CRUD方法
}
});
运行程序,点击添加按钮,查看数据库:
4、更新数据
几种常用更新方式。
最简单的一种:对已存储的对象重新设值,重新调用save()即可。对象是否已存储根据model.isSaved()方法结果判断(两种情况下返回true:已经调用model.save()添加数据了;model对象是通过LitePal提供的查询API查出来的)。先通过第一种情况验证,修改主程序:
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setName("The Lost Symbol");
book.setAuthor("Dan Brown");
book.setPages(510);
book.setPrice(19.95);
book.setPress("Unknow");
book.save();//从DataSupport类中继承的方法,其中提供了丰富的CRUD方法
book.setPrice(10.99);
book.save();
}
});
先存后改。运行程序,点击更新按钮,查看结果。
改动生效。这种更新方式只能对已储存的对象进行操作,限制性比较大。另一种更灵巧的方式,修改主程序:
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setPrice(14.95);
book.setPress("Anchor");
book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan Brown");
// 如不指定条件语句,则更新所有数据
}
});
重新运行程序。
在使用updateAll()时,当想把字段的值更新成默认值时不可使用上面的方式来set数据的(Java中任何一种数据类型字段都会有默认值,new出一个Book对象时,所有字段已被初始化成默认值)。LitePal同意提供了setToDefault()方法,传入相应列名即可实现。如:
Book book = new Book();
book.setToDefault(“pages”);
book.updateAll();
5、删除数据
主要有两种方法:第一种也是直接调用已存储对象的delete()方法(与更新中的第一种方法类似)。
另一种,修改主程序:
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DataSupport.deleteAll(Book.class, "price < ?", "15");//不指定约束条件,则删除所有数据
}
});
运行程序,点击删除按钮,查看结果:
价格低于设置值的那本书已被删除。
6、查询数据
如果希望查询这张表的所有数据。使用LitePal只需这样写:
List books = DataSupport.findAll(Book.class);
findAll()方法返回的是Book类型的List集合,自动完成了赋值操作。
修改主程序:
Button queryData = (Button) findViewById(R.id.query_data);
queryData.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 name is " + book.getName());
Log.d("MainActivity", "book author is " + book.getAuthor());
Log.d("MainActivity", "book pages is " + book.getPages());
Log.d("MainActivity", "book price is " + book.getPrice());
Log.d("MainActivity", "book press is " + book.getPress());
}
}
});
运行程序,点击查询按钮。
其他查询API:
查询Book表中第一条数据:
Book firstBook = DataSupport.findFirst(Book.class);
最后一条:
Book lastBook = DataSupport.findLast(Book.class);
通过连缀查询定制更多功能:
select()方法指定查询那几列数据,如:
List books = DataSupport.select(“name”, “author”).find(Book.class);
where()指定查询约束条件,如:
List books = DataSupport.where(“pages > ?”, “400”).find(Book.class);
order()指定结果的排序方式(默认asc升序),如:
List books = DataSupport.order(“price desc”).find(Book.class);
limit()指定查询结果数量(行):
List books = DataSupport.limit(3).find(Book.class);
offset()指定查询结果偏移量,如查询第2、3、4条数据:
List books = DataSupport.limit(3).offset(1).find(Book.class);
还可以对着5个方法进行任意连缀组合,形成复杂查询操作:
List books = DataSupport.select(“name”, “author”, “pages”).where(“pages > ?”, “400”).order(“pages”).limit(10).offset(10).find(Book.class);
LitePal仍然支持使用原生的SQL进行查询:
Cursor c = DataSupport.findBySQL(“select * from Book where pages > ? and price < ?”, “400”, “20”);
findBySQL返回的是cursor对象,需将数据一一取出。