SQLite & LitePal
自己做为一个iOS开发,看到安卓这一块的时候,那中浓烈的熟悉味道更加强烈,SQLite这种轻量级的关系型数据库的使用在移动端相差不多,iOS有FMDB,Android有LitePal, 这一篇文章好好总结一下 SQLite & LitePal,由于自己用的是Mac系统,在配置 adb的时候也遇到了一些问题,把这些问题也都说一下,避免大家跳太多的坑吧。这个我们就先说说在Mac系统下配置这个adb,因为这个不管是我们使用原生SQLite还是用LitePal,这东西都是必须的,说以先说说它的一个配置:
adb
adb是 Android SDK自带的一个调试工具,使用这个工具可以直接对连接在电脑上的手机或者模拟器进行调试操作,使用adb shell 可以对数据库和表的创建情况进行检查。它存放在SDK的platform-tools目录下,如果想要在命令行中使用这个工具,就需要先把它的路径配置到环境变量中。
Windows系统的我们就不说了,这个自己上网找,相信会有很多很多的教程,就说说在Mac系统下adb的安装教程:
先在你的SDK Manager 里面找一下你的SDK的位置,如下图两点中需要注意的地方,一个是SDK位置,一个是下载Platform - Tools:
然后打开你的终端我们继续:
1、检查一下你是不是有.bash_profile文件,打开终端 ls -a 查看一下是不是有这个文件,没有的就到下一步,有的就跳过第二步
2、没有上面查看的文件,输入 touch .bash_profile 创建文件
3、打开.bash_profile文件,对其内容进行编辑,命令如下:open -e .bash_profile
4、此时文本编辑器会打开一个文本,编辑内容如下:注意!!!下面ABC就是你在前面看到的SDK的路径!
export PATH=${PATH}:ABC/platform-tools
export PATH=${PATH}:ABC/tools
5、更新刚配置的环境变量,输入: source .bash_profile
6、检查一下是否配置成功 输入: adb
7、只要不出现command not found,那就说明配置没问题了!
SQLite
一:SQLite的创建
Android为了让我们更加方便的管理数据库,专门提供了一个SQLiteOpenHelper的抽象类,这意味的我们要是想使用它的话就得我们创建一个类去继承它,SQLiteOpenHelper中有两个抽象方法,分别是onCreate()和onUpgrade(),我们也必须在自己的类当中去重写这两个方法,分别在这两个方法中去实现创建和升级数据库的逻辑。
SQLiteOpenHelper当中有两个非常重要的实例化方法,getReadableDatabase()和getWritableDatabase(),这两个方法都可以创建或者而打开一个现有的数据库,入伙数据库已经存在就直接打开,否则会创建一个新的数据库,并返回一个可以对数据库进行操作的对象,不同的是,当数据库不可写入的时候(比如磁盘已满)。getReadableDatabase()方法返回的对象将以只读的方法打开数据库,而getWritableDatabase()方法则将出现异常。
SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数比较少的那个构造方法即可,这个构造方法中接收四个参数,第一个参数是Context,这个没什么好说的,第二个参数是数据库名称,第三个参数允许我们再查询数据的时候返回一个自定义的cursor,一般传入都是null,第四个参数是当前数据库的版本号,这个额可以对数据库进行升级操作,构建出SQLiteOpenHelper实例之后再调用前面我们说的getReadableDatabase()或getWritableDatabase()就能够创建数据库了,数据库文件会存放在/data/data/<package name >/database 目录下。此时重写的 onCreat()方法也会得到执行。所以通常会在这里做一些创建表的逻辑。
(具体代码下面)
二:SQLite的升级
我们想象这样一个场景,我们要是需要在数据库当中添加一张表那我们需要怎么办呢?简单啊,我们在创建的表的方法onCreate()里面添加一条创建表的语句就可以了啊,仔细想象这样真的可以吗?其实是不行的,因为你已经存在的数据库是没办法在走onCreate方法的, 那怎么办?把以前的程序删除了,重新安装,额。。这样做不行的,这里就要使用我们的数据库的升级了。
我们利用的就是onUpgrade()方法+前面初始化时候的版本号,接着利用上面代码,我们升级一下我们这个数据库,给里面再添加一张表。
(具体代码下面)
三:SQLite的增删查改
下面代码是上面三点的代码的总结,代码是写在一起的,下面是我们写的SQManager文件内容:
package SQManager;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
/**
* Created by skotc on 2018/7/17.
*/
public class SQManager extends SQLiteOpenHelper {
public static final String CREATE_BOOK = " create table Book (" +
"id integer primary key autoincrement" +
"author text" +
"price real" +
"pages integer" +
"name text)";
public static final String CREATE_CATEGORY = " create table Category (" +
"id integer primary key autoincrement" +
"category_name text" +
"category_code integer)";
private Context mContext;
public SQManager(Context context,String name, SQLiteDatabase.CursorFactory factory, int version){
super(context,name,factory,version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create Succeed", Toast.LENGTH_LONG).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// 这两条drop语句,如果发现数据库中已经存在表,那就将这两张表删除掉,造调用onCreate重新创建
// 这里我们有一点需要注意的是如果表已经存在,再去创建就会报错
sqLiteDatabase.execSQL("drop table if exists Book");
sqLiteDatabase.execSQL("drop table if exists Category");
onCreate(sqLiteDatabase);
}
}
再把MainActivity文件的内容展示出来:
package com.example.skotc.sqlitetest;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabaseLockedException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import SQManager.SQManager;
public class MainActivity extends AppCompatActivity {
private SQManager sqManager;
private SQLiteDatabase sqLiteDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//
sqManager = new SQManager(this,"BookStore",null,1);
//sqManager = new SQManager(this,"BookStore",null,1);
Button SQButton = (Button)findViewById(R.id.SQButton);
SQButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 第一次调用的时候检测到没有BookStore这个数据库就回去创建这个数据库
sqLiteDatabase = sqManager.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name","我是中国人");
values.put("author","zhangxu");
values.put("pages",500);
values.put("price",15.4);
//insert 第一个参数是表的名称 第二个参数是用于在未指定添加的情况下给某些可为空的列自动复制为NULL
//第三个参数是我们的ContentValues对象
sqLiteDatabase.insert("Book",null,values);
//组装第二条数据
values.put("name","我在广州");
values.put("author","james");
values.put("pages",343);
values.put("price",19.4);
sqLiteDatabase.insert("Book",null,values);
//这里有个问题需要我们注意一下
//为什么我们没有在ID的哪一列没有赋值呢?这还少因为在前面创建表的时候,我们将ID设置为了自增
//它的值会在入库的时候自动的增加
//先说这句更新的意思
//整体语句的意思是把书名叫我在广州的书的价格修改为10.0
values.put("price","10.0");
//说说update方法的参数
//第一和表名,第二个是修改的values,第三,第四是用于约束更新某一行或者几行的数据
//更新所有name = ?的行,而?是一个占位符,在第四个参数提供了一个字符串数组为第三个参数中的每一个占位符
//提供相应的内容
sqLiteDatabase.update("Book", values, "name = ?", new String[]{"我在广州"});
//delete删除
//第一和表名,第二个参数是删除的条件,第三个参数是给约束条件赋值,没和前面的更新道理相同
sqLiteDatabase.delete("Book","page > ?",new String[]{"300"});
// 查询
// 这里需要注意的就是query方法的参数解析
// 第一个参数是表名称
// 第二个参数用于指定查询那一列,要是没有至此那个就查询所有
// 第三,第四各参数用于约束查询某一行或者几行的数据,这个和前面的一样道理
// 第五个参数用于指定需要去group by的列,不指定则表示不需要对查询结果进行 group by操作
// 第六个参数用于对第五步 group by 之后的数据进行进一步的过滤,不指定就不进行过滤
// 第七个参数用于指定查询结果的排序方式,不指定就是默认排序
Cursor cursor = sqLiteDatabase.query("Book",null,null,null,null,null,null);
if (cursor.moveToFirst()){
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","name = "+name);
Log.d("MainActivity","author = "+author);
Log.d("MainActivity","pages = "+pages);
Log.d("MainActivity","price = "+price);
}while (cursor.moveToNext());
}
cursor.close();
}
});
}
}
LitePal是郭神(郭霖)在2014年的杰作,三年后在github上有了一个更新,故来学习一番,没想到还挺好用,这里做下笔记。LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发时最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表、増删改查的操作。并且LitePal很“轻”,jar包只有100k不到,而且近乎零配置,这一点和hibernate这类的框架有很大区别。
基本的配置:
1、引入我么的LitePal包
由于我们的LitePal也是提交到jcenter的,所以我们可以通过在app/build.gradle 文件中声明该开源库的引用就可以了,代码如下:(LitePal的版本已经来到2.0)
2、配置一下我们的litepal.xml文件,在app/src/main路径下通过 New - Directory 创建一个assect 目录, 然后再assect目录下新建一个 litepal.xml文件。接着编辑里面的内容,内容如下:
3、最后就是修改一下我们的 AndroidMainfest.xml文件了,将我们的项目的application配置为 org.litepal,litePalApplication,这样才能让LitePal所有功能正常的使用,之后我们会在补充关于 application的内容的时候会讲解一下为什么!
它的使用:
关于它的映射类这部分的类容我们和关于它CRUD的操作依据里面的注意事项就直接上代码,把他们放在代码中说:
映射类的创建就不说了,你自己创建一个java类,添加变量重写get以及set方法就行了,关键的点是在进行关于它CRUD的操作的时候,在以前是需要我们把我们的映射类继承DataSupport的,但现在这个类已经被废弃了,而是选择使用 LitePalSupport,这点在代码中有具体的提现:
看看我们定义的映射类,注意写的注释:
最后就是我们关于它的CRUD的操作: