?引言
概念
SQLite数据库,和其他的SQL数据库不同, 我们并不需要在手机上另外安装一个数据库软件,Android系统已经集成了这个数据库;
特点
SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用
不仅支持标准SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便
SQLite支持五种数据类型
- NULL
- integer(整型)
- real(浮点型)
- text(文本类型)
- blob(二进制类型)
SQlite 通过文件来保存数据库
- 一个文件就是一个数据库
- 数据库中又包含多个表格
- 表格里又有多条记录
- 每条记录由多个字段构成
- 每个字段都有对应的值
?创建数据库
Android为了让我们能够更加方便地管理数据库,专门提供了一个 SQLiteOpenHelper 帮助类;
借助这个类就可以非常简单地对数据库进行创建和升级。
SQLiteOpenHelper 是一个抽象类,这意味着如果我们想要使用它的话,就需要创建一个自己的帮助类去继承它;
SQLiteOpenHelper 中有两个抽象方法,分别是 oncreate() 和 onUpgrade() ;
onCreate(database) : 数据库第一次被创建时被调用
onUpgrade(database,oldVersion,newVersion) : 在数据库的版本发生变化时会被调用
- 一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的
- 假设数据库现在的版本是 1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构
- 为了实现这一目的,可以把原来的数据库版本设置为 2,或者其他与旧版本号不同的数字即可
我们必须在自己的帮助类里面重写这两个方法,然后分别在这两个方法中去实现 创建、升级数据库 的逻辑。
SQLiteOpenHelper 中还有两个非常重要的实例方法: getReadableDatabase() 和 getWritableDatabase() 。
这两个方法都可以 创建或打开 一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),
并返回一个可对数据库进行读写操作的对象。
不同的是,当数据库不可写入的时候(如磁盘空间已满):
- getReadableDatabase() 方法返回的对象将以只读的方式去打开数据库
- 而 getWritableDatabase() 方法则将出现异常
SQLiteOpenHelper 中有三个构造方法可供重写,一般使用参数少一点的那个:
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
该构造方法中接收四个参数:
- Context context :这个没什么好说的,必须有这个才能对数据库进行操作
- String name :第二个参数是数据库名,创建数据库时使用的就是这里指定的名称
- SQLiteDatabase.CursorFactory factory :第三个参数允许我们在查询数据的时候返回一个自定义的 Cursor,一般都是传入null
- int version :第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作
构建出 SQLiteOpenHelper 的实例之后,再调用它的 getReadableDatabase() 或 getWritableDatabase() 方法就能够创建数据库了;
数据库文件会存放在 /data/data/<package name>/databases/ 目录下;
此时,重写的 onCreate() 方法也会得到执行,所以通常会在这里去处理一些创建表的逻辑。
?通过代码深入理解
准备工作
首先新建一个 TestDatabase 项目。
在该项目中新建 MyDatabaseHelper 类,继承自 SQLiteOpenHelper;
MyDatabaseHelper.java
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book (" + "id integer primary key autoincrement," + "name text," + "price real)"; private Context mContext; public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); Toast.makeText(mContext,"建表成功",Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} }可以看到,我们把建表语句定义成了一个字符串常量,然后在 onCreate() 中调用了 db.execSQL(CREATE_BOOK); 去执行这条建表语句;
之后,弹出一个 Toast 提示建表成功;
这样就可以保证在数据库创建的同时创建 Book 表;
在 SQL 中,Book 表的建表语句如下:
create table Book( id integer primary key autoincrement, name text, price real)其中,设置 id 为 primary key,并用 autoincrement 关键字表示 id 列是自增长的。
接下来,修改 activity_main.xml 中的代码;
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <Button android:id="@+id/create" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="建表"/> </LinearLayout>布局文件很简单,就是加入了一个按钮,用于创建数据库。
最后,修改 MainActivity.java 中的代码;
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private MyDatabaseHelper helper; private Button mBtnCreate; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); helper = new MyDatabaseHelper(this,"BookStore.db",null,1); mBtnCreate = findViewById(R.id.create); mBtnCreate.setOnClickListener(this); } @Override public void onClick(View v) { switch(v.getId()){ case R.id.create: helper.getWritableDatabase(); break; } } }这里我们在 onCreate() 方法中构建了一个 MyDatabaseHelper 对象,并且通过构造函数的参数将数据库名指定为 BookStore.db,版本号指定为 1;
然后在 mBtnCreate 按钮 的点击事件里调用了 getWritableDatabase() 方法;
这样当第一次点击 mBtnCreate 按钮时,就会检测到当前程序中并没有 BookStore.db 这个数据库,
于是会创建该数据库并调用 MyDatabaseHelper 中的 onCreate() 方法,这样 Book 表也就得到了创建,然后会弹出一个 Toast 提示创建成功。
再次点击 mBtnCreate 按钮时,会发现此时已经存在 BookStore.db 数据库了,因此不会再创建一次。
运行效果
此时 BookStore.db数据库 和 Book表 应该都已经创建成功了,因为当你再次点击 mBtnCreate 按钮时,不会再有 Toast 弹出;
可是怎样才能证实它们的确创建成功了?
打开 Android Device Monitor(不知道什么是 ADM 的小伙伴可以参考我的这篇博客??),
找到 /data/data/com.example.testdatabase/databases/ 目录:
你会发现该目录下多了一个 BookStore.db 文件,但是看不到 Book 表,这可如何是好?
下面介绍一下通过使用 adb shell 方式来对数据库和表的创建情况进行检查。
adb 是 Android SDK 中自带的一个调试工具,使用这个工具可以直接对连接在电脑上的手机或模拟器进行调试操作;
它存放在 Android SDK 的 platform-tools 目录下,如果想要在命令行中使用这个工具,就需要先把它的路径配置到环境变量中;
如果不知道你的 Android SDK 安装在哪的小伙伴,可以通过以下方式找到:
点击【Tools】->【SDK Manager】;
找到 Android SDK 的安装路径;
在【电脑】中打开该路径,并找到【platform-tools】文件夹;
复制该路径,打开【环境变量】,在【系统变量】里找到【Path】并点击编辑,将 platform-tools 目录配置进去即可;
配置好了环境变量后,就可以使用 adb 工具了;
通过【Win+R】打开命令行界面,输入 adb shell,就会进入到设备的控制台;
其中,# 符号是超级管理员的意思,也就是说,现在你可以访问模拟器中的一切数据;
如果你的命令行上显示的是 $,那么就表示你现在是普遍管理员,需输入 su 命令切换成超级管理员,这样才能执行以下操作;
接下来使用 cd 命令进入到 /data/data/com.example.testdatabase/databases/ 目录下;
(偷偷告诉你,鼠标右击可以实现粘贴功能)
使用 ls 命令查看该目录里的文件;
这个目录下出现了两个数据库文件,一个正是我们创建的 BookStore.db;
而另一个 BookStore.db-journal 则是为了让数据库能够支持事务而产生的临时日志文件,通常情况下这个文件的大小都是 0 字节;
接下来我们就要借助 sqlite 命令来打开数据库了,只需要键入【sqlite3 数据库名】即可;
这时就已经打开了 BookStore.db 数据库,现在就可以对这个数据库中的表进行管理了;
首先来看一下目前数据库中有哪些表,键入 .table 命令;
可以看到,此时数据库中有两张表:
- android_metadata表 是每个数据库中都会自动生成的,不用管它
- 而另外一张 Book表 就是我们在 MyDatabaseHelper 中创建的了
这里还可以通过 .schema 命令来查看它们的建表语句;
由此证明,BookStore.db数据库 和 Book表 确实已经创建成功了;
之后键人 .exit 或 .quit 命令可以退出数据库的编辑,再键入 exit 命令就可以退出设备控制台了。