《第一行代码》阅读笔记(二十一)——SQLite数据库(CRUD)

书的开头就是一顿夸赞,反正SQLite强无敌!

写在最前

现在使用第三方的可视化工具使用的比较多了,这里简单提一嘴。

就是这个Navicat for Sqlite。安装了这个软件后,就要找到库文件位置。如果你是真机测试的话(虚拟机没试过,应该是一样的,不一样的话大家善用百度),右下角的Device File Explorer->data->data->包名->你建的数据库

就是这样一个文件,就是数据库文件。

打开Connection->SQLite,如下图

弹出一个界面

将刚才的数据库文件添加到画框的位置即可,查看。

创建数据库

第一步:创建一个MyDatabaseHelper

package com.firstcode.databasetest;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

import androidx.annotation.Nullable;

public class MyDatabaseHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book("
            + "id integer primary key autoincrement,"
            + "author text,"
            + "price real,"
            + "pages integer,"
            + "name text)";

    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, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

首先我们看MyDatabaseHelper,继承自SQLiteOpenHelper。类中有一个字符串,这个其实就是非常简单的SQL语句,其中create就是创建表,integer表示整型,real表示浮点型,text表示文本类型。primary key 将id列设为主键,autoincrement关键字表示id列是自增长的。(注意这里所写的主键自增和MySQL中的主键自增是不同的,所以SQLite语法可能和MySQL的语法有些许不同)

其后编写了一个构造函数,这个构造方法中接收4个参数,第一个参数是Context,这个没什么好说的,必须要有它才能对数据库进行操作。第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor, 一般都是传入null。 第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。

然后就是重写的两个方法,onCreate和onUpgrade。onCreate在这里很简单,就是把之前写好的SQL语句执行了。

第二步:修改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">

    <Button
        android:id="@+id/create_database"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create database" />

</LinearLayout>

第三步:修改MainActivity

package com.firstcode.databasetest;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper databaseHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        databaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                databaseHelper.getWritableDatabase();
            }
        });
    }
}

到这里都没什么特别的,书中主要介绍了SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase()和 getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。

运行测试即可,非常简单。之后书中还介绍如何找到这个表的存在,就不多赘述。如果找不到的朋友参考以下链接
在Mac上配置Android studio的adb
阅读郭林《第一行代码》的笔记——第6章 数据存储全方案,详解持久化技术

升级数据库

我们需要更新数据库,再见一张Category表

 public static final String CREATE_CATEGORY = "create table Category("
            + "id integer primary key autoincrement,"
            + "category_name text,"
            + "category_code integer)";

如果想要运行这段代码,需要做两件事情

第一:在onCreate()函数中执行语句,但是光这样是不够的,因为onCreate()函数在创建之后是不会再运行的。 所以我们需要用到onUpdate()函数。

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }

先删了之前的表,再执行onCreate()建新的。不删除会报错。
第二:使用更大的版本号来实现更新。

        databaseHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);

——第一行代码
接下来的问题就是如何让onUpgrade( )方法能够执行了,还记得SQLiteOpenHelper的构造方法里接收的第四个参数吗?它表示当前数据库的版本号,之前我们传入的是1,现在只要传入一个比1大的数,就可以让onUpgrade()方法得到执行了。

增删改查十分简单,而且SQLite内置的函数,都不需要写SQL的。让我们来看看吧

添加数据

——第一行代码
SQLiteDatabase中提供了一个insert()方法,这个方法就是专门用于添加数据的。它接收3个参数,第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字。第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null即可。第三个参数是一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加数据传人即可。

需求:添加两本新书

代码演示如下

SQLiteDatabase db = databaseHelper.getWritableDatabase();
                ContentValues values = new ContentValues();

                //开始添加第一条数据
                values.put("name","The Da Vinci Code");
                values.put("author","Dan Brown");
                values.put("pages","454");
                values.put("price","16.96");
                db.insert("Book", null, values);
                values.clear();
                //开始添加第二条数据
                values.put("name","The Lost Symbol");
                values.put("author","Dan Brown");
                values.put("pages","510");
                values.put("price","19.96");
                db.insert("Book", null, values);

修改数据

——第一行代码
学习完了如何向表中添加数据,接下来我们看看怎样才能修改表中已有的数据。SQLiteDatabase中也提供了-一个非常好用的update()方法, 用于对数据进行更新,这个方法接收4个参数,第一个参数和insert()方法一样,也是表名,在这里指定去更新哪张表里的数据。第二个参数是ContentValues对象,要把更新数据在这里组装进去。第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行。

需求:修改第一本书的价格

代码演示如下

                SQLiteDatabase db = databaseHelper.getWritableDatabase();
                ContentValues values = new ContentValues();

                values.put("price",10.99);
                db.update("Book", values, "name = ?", new String[]{"The Da Vinci Code"});

update的前两个参数没啥可说的,和insert一样,后面的就是where的一个判断语句,例子中的就是where name = ?,不知道大家有没有用过jdbc之类的数据库连接池,一般就是占位符,而它的值就是第四个参数String[],这样就可以满足之前的需求了,可以更改一个数值,也能更改多个数值。

删除数据

——第一行代码
删除数据对你来说应该就更简单了,因为它所需要用到的知识点你全部已经学过了。SQLiteDatabase中提供了一个delete()方法,专门用于删除数据,这个方法接收3个参数,第一个参数仍然是表名,这个已经没什么好说的了,第二、第三个参数又是用于约束删除某一行或某几行的数据,不指定的话默认就是删除所有行。

代码演示如下

                SQLiteDatabase db = databaseHelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[]{"5000"});

查看数据

——第一行代码
相信你已经猜到了,SQLiteDatabase 中还提供了一个query()方法用于对数据进行查询。这个方法的参数非常复杂,最短的一个方法重载也需要传入7个参数。那我们就先来看一下这7个参数各自的含义吧。第一个参数不用说,当然还是表名,表示我们希望从哪张表中查询数据。第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列。第三、第四个参数用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。第五个参数用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作。第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤。第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。更多详细的内容可以参考下表。其他几个query( )方法的重载其实也大同小异,你可以自己去研究一下,这里就不再进行介绍了。

如果大家了解过SQL语言,其实很好理解。

代码演示如下

 SQLiteDatabase db = databaseHelper.getWritableDatabase();
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        //遍历Cursor对象,取出数据并打印
                        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"));
                    } while (cursor.moveToNext());
                }
                cursor.close();

直接使用SQL操作

如图所示,如果之前有SQL基础的话,完全可以使用这种方式。毕竟学习一种新的方式也是有时间的成本在里面的。

posted @ 2020-08-01 20:03  朱李洛克  阅读(393)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css