一 使用adb工具
下载什么的,环境配置什么的,就不说了。
1.进入cmd
2.输入 :adb shell
输入 :su 获得超级管理员权限
3.进入项目的目录
cd /data/data/com.example.项目名称/databases
4.输入 :ls
查看数据库文件,一般出现两个,一个是我们自己创建了的数据库文件,一个是数据文件支持的日志文件。
5. 输入 :# sqlite3 数据文件名称.db
进入数据库
6.接下来就可以进行一系列的操作了
.table 查看表
.schema 查看创建语句0
select * from …
之前书上讲了Sqlite,我觉得Litepal用的更舒服一点
作者为什么要推荐写LitePal呢,大概是因为他是LitePal的作者把,那个好用,这个仁者见仁智者见智,适合就好。
二. 使用Litepal
LitePal 采取的是对象关系映射(ORM)的模式。
ORM: 我们使用的编程语言是面向对象语言,而使用的数据库则是关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射。也就是直接可以用面向对象,不必要用sql了。
1. 配置LitePal
我们需要在app/build.gradle文件的dependencies闭包中添加:
implementation 'org.litepal.android:core:2.0.0'
后面是版本号我用的2.0.0,现在有3.0.0 。
最新的可以到github上去看。
我不用3.0.0是因为,3.0中创建数据库LitePal.getDatabase();这个方法用不了,我看了github也没找到解决办法。
书上写的是 compile 现在它已经被抛弃,是个孤儿,现在都用implementation了。
接下来在main目录下新建一个assets目录,里面在新建一个litepal.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="1"></version>
<list>
</list>
</litepal>
< dbname > 指定数据库名称
< version > 指定数据库版本号
< list > 指定所有的映射模型
在AndroidManifest.xml中添加
android:name=“org.litepal.LitePalApplication”
<?xml version="1.0" encoding="utf-8"?>
<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:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
修改activity_main.xml里面的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database"
/>
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"
/>
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="update data"
/>
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"
/>
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data"
/>
</LinearLayout>
就是加几个CRUD的按钮!
2.创建和升级数据库
定义一个Book类
import org.litepal.crud.LitePalSupport;
public class Book extends LitePalSupport {
private int id;
private String author;
private double price;
private int pages;
private String name;
private String press;
//类中的每一个字段都对应数据库表中的每一列
public void setPress(String press) {
this.press = press;
}
public String getPress() {
return press;
}
public int getId() {
return id;
}
public String getAuthor() {
return author;
}
public double getPrice() {
return price;
}
public int getPages() {
return pages;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setAuthor(String author) {
this.author = author;
}
public void setPrice(double price) {
this.price = price;
}
public void setPages(int pages) {
this.pages = pages;
}
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>
< mapping >声明我们要配置的映射模型类
现在我们来创建数据库吧
在MainActivity中这样写
@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 view) {
LitePal.getDatabase();
}
});
}
点击Button (cretaDatabase)调用LitePal.getDatabase()方法
就会创建数据库了
在adb中查看如下
这里我们再加一张Category的表,就在新建一个Category的类
public class Category {
private int id;
private String categoryName;
private int categoryCode;
public void setId(int id) {
this.id = id;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public void setCategoryCode(int categoryCode) {
this.categoryCode = categoryCode;
}
}
在litepal.xml中修改
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="2"></version>
<list>
<mapping class="com.example.litepaltest.Book"></mapping>
<mapping class="com.example.litepaltest.Category"></mapping>
</list>
</litepal>
要进行改变数据的话,要记得把version版本号加1
3.往数据库中添加数据
LitePal进行表管理操作时不需要模型类有任何的继承结构,但是进行CRUD操作是就不行了,必须要继承LitePalSupport。书上继承的是DataSupport,这个已经被抛弃了,DataSupport也是一个孤儿。
public class Book extends LitePalSupport {
..........
}
然后来修改Button(addData)
Button addData=(Button)findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Book book=new Book();
book.setName("The Da Vinci Code");
book.setAuthor("Dan Brown");
book.setPages(454);
book.setPrice(16.96);
book.setPress("Unknown");
book.save();
}
});
首先是创建了一个Book的实例,然后调用Book类中的各种set方法对其进行设置,最后在调用book.save()方法,这个方法是继承来的。
在adb中输入select * from Book;
4.使用LitePal更新数据
对于Litepal来说,对象是否已存储就是根据调用model.isSaved()方法的结果来判断的,返回true表示已存储,false就是为存储。
当用过modle.save()方法,此时model就会被认为是已存储了的
Button updateData=(Button)findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
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();
book.setPrice(10.99);
book.save();
}
});
这里就是只会将19.95改成10.99,而不会去创建新的对象了,因为LitePal会发现当前的book对象是已存储了的。
上面这种方法,对更新数据限制性比较大,我们来看一个灵活一点的
Button updateData=(Button)findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Book book=new Book();
book.setPrice(14.95);
book.setPress("Anchor");
book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brown");
}
});
1)我们首先new一个Book的实例,然后直接调用setPrice和setPress方法来设置更新的数据,最后在调用updateAll()方法去执行更新操作。
2)updateAll方法中可以指定约束条件和sql中where差不多,如果不指定约束条件的话,就表示更新所有数据。
3)这里我们指定将所有书名是The Lost Symbol并且作者是Dan Brown的书的价格更新为14.95,出版社更行为Anchor
不过,在使用updateAll()方法时,还有一个非常重要的知识点是你需要知晓的,就是当你想把一个字段的值更新成默认值时,是不可以使用上面的方式来set数据的。我们都知道,在Java中任何一种数据类型的字段都会有默认值,例如int类型的默认值是0,boolean类型的默认值是false,String类型的默认值是null。那么当new出一个Book对象时,其实所有字段都已经被初识化成默认值了,比如说pages字段的值就是0。因此,如果我们想把数据库表中的pages列更新成0,直接调用book.setpages(0)是不可以的,因为即使不调用这行代码,pages字段本身也是0,Litepal此时是不会对这个列进行更新的。对于所有想要将为数据更新成默认值的操作,Litepal统一提供了一个setToDefault()方法,然后传入相应的列名就可以实现了。
比如我们可以这样写
Book book=new Book();
book.setToDefault("Pages");
book.updateAll();
这段代码的意思是,将所有书的页数都更新为0,因为updateAll()方法中没有指定约束条件,因此更新操作对所有数据都有效。
5.使用LitePal删除数据
第一种比较简单,就是调用存储对象的delete方法就好了。
LitePal.delete(这里写参数)
看一下delete的原码
This means that the record 1 in person table will be removed.
*
* @param modelClass
* Which table to delete from by class.
* @param id
* Which record to delete.
* @return The number of rows affected. Including cascade delete rows.
*/
public static int delete(Class<?> modelClass, long id) {
synchronized (LitePalSupport.class) {
int rowsAffected = 0;
SQLiteDatabase db = Connector.getDatabase();
db.beginTransaction();
try {
DeleteHandler deleteHandler = new DeleteHandler(db);
rowsAffected = deleteHandler.onDelete(modelClass, id);
db.setTransactionSuccessful();
return rowsAffected;
} finally {
db.endTransaction();
}
}
}
我们来看另一种方式
Button deleteButton=(Button)findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
LitePal.deleteAll(Book.class,"price < ?","15");
}
});
书上写的是DataSupport现在已经被抛弃了是个孤儿,现在大家都喜欢用LitePal
LitePal.deleteAll(Book.class,“price < ?”,“15”);
指定删除Book表中price<15的数据
我们看一下效果:
看小于15的数据已经被删除了
6.使用LitePal查询数据
Button queryButton=(Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
List<Book> books= LitePal.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());
}
}
});
LitePal.findAll(Book.class);返回的是一个List对象,LitePal已经帮我们完成么赋值操作
除了findAll方法 Litepal还有许多其他的查询API
查询Book表中第一条数据:
Book firstBook=LitePal.findFirst(Book.class);
查询Book表中最后一条数据:
Book lastBook=LitePal.findLast(Book.class);
select()方法用于指定查询哪几列的数据,对应了SQL当中的select关键字。比如只查name和author着两列的数据
List<Book> books=LitePal.select("name","author").find(Book.class);
where()方法用于指定查询的约束条件,对应了SQL当中的where关键字。比如只查页数大于400的数据
List<Book> books=LitePal.where("pages > ?","400").find(Book.class);
order()方法用于指定结果的排序方式,对应了SQL当中的order by关键字。比如将查询结果按照书价从高到低排序
List<Book> books=LitePal.order("price desc").find(Book.class);
limit()方法用于指定查询结果的数量。比如只查表中的前3条数据
List<Book> books=LitePal.limit(3).find(Book.class);
offset()方法用于指定查询结果的偏移量。比如查询表中的第2条,第3条,第4条数据
List<Book> books=LitePal.limit(3).offset(1).find(Book.class);
对这5个方法综合运用
List<Book > books=LitePal.select("name","author","pages")
.where("pages > ?","400")
.roder("pages")
.limit(10)
.offset(10)
.find(Book.class);
LitePal中也可以用sql
使用LitePal.findBySQL()方法 返回一个Cursor游标对象,然后用Sqlite的方法去访问,这边我就不讲了,有兴趣百度去吧。