我博客的相关说明
这部分算是对3.数据库储存的补充升级,介绍如何通过LitePal来进行CRUD操作。
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,将平时开发最常用的一些数据库功能进行了封装,使得不用编辑一条SQL语句就能完成CRUD的工作。LitePal使用文档
在app/build.gradle
文件中声明该开源库的引用就可以了。
dependencies
闭包中添加:compile 'org.litepal.android:core:1.4.1'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'org.litepal.android:core:1.4.1'
}
<litepal>
<dbname value="BookStore1">dbname>
<version value="1">version>
<list>
list>
litepal>
其中
标签用来指定数据库名,
用于指定数据库版本号,用于指定所有的映射类型。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ifinder.mydaily4">
<application
android:name="org.litepal.LitePalApplication">
···
application>
manifest>
LitePal采取对象关系映射(ORM)的模式,将Java的面向对象的语言和SQL的结构化查询语言建立对应关系。之后就可以通过面向对象的思想操作数据库。
与SQLiteOpenHelper不同,使用LitePal建表时,我们可以先建立一个Book类,而类的属性就是之前表中的内容。然后通过Java bean来操作类中的各个属性。
public class Book1 extends DataSupport {
private int id;
private String name;
private String author;
private double price;
private int pages;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
···
}
生成setter和getter方法的快捷键(AS 3.5):定义好各个属性之后,选中,按alt+shift+insert
在弹出菜单中选择Getter and Setter
Book类对应数据库中的Book表,类中的每一个字段对应了数据库表中的每一列。
修改litepal.xml中的代码
<litepal>
···
<list>
mapping>
list>
litepal>
用
标签来声明配置的映射模型类。只要建立映射在
标签下配置就可以。
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lite_pal_test);
BTN_create = findViewById(R.id.Btn_create);
BTN_create.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LitePal.getDatabase();
}
});
}
}
运行程序,点击Create按钮。使用adb shell查看数据库。
到这里如果报错的话可以去看这一篇文章哦!
可以看到BookStore1数据库和Book1表已经建立好了。
可以通过.schema命令来查看建表语句:
LitePal还有一个很重要的功能就是能够在升级数据库的同时保存我们先前的数据。
让我们在Book1表里加入一列press(出版社),并且再建立一张Category1表:
public class Category1 {
private int id;
private String categoryName;
private int categoryCode;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
···
}
public class Book1 {
···
private String press;
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
···
}
<litepal>
<dbname value="BookStore1">dbname>
<version value="2">version>
<list>
<mapping class="com.ifinder.mydaily4.Book1">mapping>
<mapping class="com.ifinder.mydaily4.Category1">mapping>
list>
litepal>
运行程序,点击Create按钮。用adb shell查看数据库。
可以看见,更新版本后,press列和Category表都操作成功了。
使用LitePal储存数据,只要实例化之前创建的表模型,再将所有数据都用setter()
方法设置,最后调用save()
方法就可以了!
修改主程序文件:
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_adddata,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lite_pal_test);
···
BTN_adddata.findViewById(R.id.Btn_adddata);
BTN_adddata.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book1 book1 = new Book1();
book1.setName("The Da Vinci Code");
book1.setAuthor("Dan Browm");
book1.setPages(355);
book1.setPrice(36.7);
book1.setPress("Unknown");
book1.save();
}
});
}
}
点击Add按钮,使用adb shell工具查看数据库:
可以看到我们的各个信息已经添加到了数据库里!
save()
方法更新对象更新LitePal数据最简单的方法是将已储存的对象重新赋值,然后调用save()
方法。
已储存对象:
对于LitePalestine,已储存的对象是根据调用model.isSaved()
方法的结果来判断的,true为已储存,false为未储存。
调用model.save()
方法添加数据、model
对象是通过API查询出来的结果,二者都会使model.save()
方法的返回值为true
修改主程序代码,添加新的书籍信息:
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_adddata,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lite_pal_test);
···
BTN_update = findViewById(R.id.Btn_update);
BTN_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book1 book1 = new Book1();
book1.setName("The Lost Symbol");
book1.setAuthor("Dan Brown");
book1.setPages(430);
book1.setPrice(39.8);
book1.setPress("Unknown");
book1.save();
book1.setPrice(42.9);
book1.save();
}
});
}
}
这里添加数据后,book1调用了save()
方法,而更改价格后再一次调用save()
方法回让LitePal认为数据是已经储存的,所以不会向表中添加新数据,而是会直接更新当前数据。运行程序,点击update按钮,查看数据库内文件。
可以看到,第二条数据成功添加,并且price也已经更新为相应的42.9了。
updateAll()
方法更新对象修改主程序代码:
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_adddata,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
···
BTN_update = findViewById(R.id.Btn_update);
BTN_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book1 book1 = new Book1();
book1.setPrice(29.8);
book1.setPress("Anchor");
book1.updateAll("name = ? and Author = ?","The Lost Symbol","Dan Brown");
}
});
}
}
可以看到,updateAll()
方法制定了一个约束条件,这里指定书名为The Lost Symbol作者为Dan Brown的书籍价格更新为29.8。让我们运行程序查看结果。
可以看到,数据更新成功了。
LitePal更新默认值时,时不能调用
set
方法的,这时候更新就可以这么写:
Book1 book1 = new Book1();
book1.setToDefault("price");
book1.updateAll("name = ? and Author = ?","The Lost Symbol","Dan Brown");
delete()
方法删除数据该方法和更新数据时的save()
方法很像,当对象被识别为已储存对象时,该方法才会被执行。
public void onClick(View v) {
Book1 book1 = new Book1();
book1.setName("海边的卡夫卡");
book1.setAuthor("村上村树");
book1.setPages(430);
book1.setPrice(39.8);
book1.setPress("Unknown");
book1.save();
book1.delete();
}
点击按钮执行这个方法后可以看到数据库内容没有什么变化,因为该条信息添加成功后立即被delete()
方法删除了。
deleteAll()
方法删除数据修改主程序代码:
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_adddata,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
···
BTN_delate = findViewById(R.id.Btn_delate);
BTN_delate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DataSupport.deleteAll(Book1.class,"price > ?","30");
}
});
}
}
这里我们希望删除价格大于40的书籍信息。运行程序点击delete按钮,查看数据库。
可以看到price大于30的数据已经被我们成功删除了。
deleteAll()
和updateAll()
一样,如果不指定约束条件的话,会删除/更新所有数据。findAll()
方法查询数据List
findAll()
方法返回的是一个Book类型的List集合。LitePal会自动帮我们完成赋值操作。
修改主程序代码:
public class LitePal_test extends AppCompatActivity {
private Button BTN_create,BTN_adddata,BTN_delate,BTN_query,BTN_update;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
···
BTN_query = findViewById(R.id.Btn_query);
BTN_query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<Book1> books = DataSupport.findAll(Book1.class);
StringBuilder sb = new StringBuilder();
for(Book1 book1: books){
sb.append(book1.getName()+"\n");
sb.append(book1.getAuthor()+"\n");
sb.append(book1.getPages()+"\n");
sb.append(book1.getPrice()+"\n");
sb.append(book1.getPress()+"\n");
}
Toast.makeText(getApplicationContext(),sb,Toast.LENGTH_SHORT).show();
}
});
}
}
在for循环里遍历Book1对象,然后使用StringBuilder拼接得到的查询数据。点击query按钮:
可以看到,查询的数据已经成功打印了!
findLast()
Book1 lastBook = DataSupport.findLast(Book1.class);
findFirst()
Book1 firstBook = DataSupport.findFirst(Book1.class);
select()
List books = DataSupport.select("name").find(Book1.class);
where()
List books = DataSupport.where("pages > ?","400").find(Book1.class);
order()
limit()
List books = DataSupport.limit(3).find(Book1.class);
offset()
List books = DataSupport.limit(3).offset(3).find(Book1.class);
List<Book1> books = DataSupport.select("name","author","pages")
.where("pages > ?","400")
.order("pages")
.limit(10)
.offset(10)
.find(Book1.class);
这段代码就表示,查询Book1表中第11~12条满足页数大于400这个条件的name、author、pages这三列数据,并且将查询结果按pages升序排列。