安卓基础之《(12)—数据存储(2)数据库SQLite》

一、数据库管理器SQLiteDatabase

1、SQLiteDatabase是SQLite的数据库管理类,它提供了若干操作数据表的API

2、管理类API,用于数据库层面的操作
(1)openDatabase:打开指定路径的数据库
(2)isOpen:判断数据库是否已打开
(3)close:关闭数据库
(4)getVersion:获取数据库的版本号
(5)setVersion:设置数据库的版本号

3、事务类API,用于事务层面的操作
(1)beginTransaction:开始事务
(2)setTransactionSuccessful:设置事务的成功标志
(3)endTransaction:结束事务

4、数据处理类API,用于数据表层面的操作
(1)execSQL:执行拼接好的SQL语句
(2)delete:删除符合条件的记录
(3)update:更新符合条件的记录
(4)insert:插入一条记录
(5)query:执行查询操作,返回结果集的游标
(6)rawQuery:执行拼接好的SQL查询语句,返回结果集的游标

5、openOrCreateDatabase
创建或打开数据库,数据库如果不存在就创建它,如果存在就打开它

public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory)
说明:
(1)name:数据库路径
(2)mode:打开模式
(2)factory:返回数据集的游标工厂

6、deleteDatabase
删除数据库

7、例子
activity_datebase.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".DatabaseActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_database_create"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="创建数据库"
            android:textSize="17sp"/>

        <Button
            android:id="@+id/btn_database_delete"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="删除数据库"
            android:textSize="17sp"/>
    </LinearLayout>

    <TextView
        android:id="@+id/tv_database"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

DatabaseActivity.java

package com.example.chapter06;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class DatabaseActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tv_database;
    private String mDatabaseName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_datebase);

        tv_database = findViewById(R.id.tv_database);

        Button btn_database_create = findViewById(R.id.btn_database_create);
        Button btn_database_delete = findViewById(R.id.btn_database_delete);

        btn_database_create.setOnClickListener(this);
        btn_database_delete.setOnClickListener(this);

        // 生成一个测试数据库的完整路径
        mDatabaseName = getFilesDir() + "/test.db";

    }

    @Override
    public void onClick(View view) {
        String desc = null;

        if (view.getId() == R.id.btn_database_create) {
            // 创建或打开数据库,数据库如果不存在就创建它,如果存在就打开它
            SQLiteDatabase db = openOrCreateDatabase(mDatabaseName, Context.MODE_PRIVATE, null);
            desc = String.format("数据库%s创建%s", mDatabaseName, (db!=null) ? "成功" : "失败");
            tv_database.setText(desc);

        } else if (view.getId() == R.id.btn_database_delete) {
            // 删除数据库
            boolean result = deleteDatabase(mDatabaseName);
            desc = String.format("数据库%s删除%s", mDatabaseName, result ? "成功" : "失败");
            tv_database.setText(desc);
        }
    }
}

8、运行结果

创建数据库

/data/data/包名/files目录下

删除数据库

二、数据库帮助器SQLiteOpenHelper

1、SQLiteOpenHelper是Android提供的数据库辅助工具,用于指导开发者进行SQLite的合理使用

2、SQLiteOpenHelper的具体使用步骤如下
(1)新建一个继承自SQLiteOpenHelper的数据库操作类,提示重写onCreate和onUpgrade两个方法
(2)封装保证数据库安全的必要方法
(3)提供对表记录进行增加、删除、修改、查询的操作方法

3、由于读和写的锁是不一样的,所以要提供两个SQLiteDatabase实例

4、SQLiteOpenHelper的onCreate方法只会在数据库第一次被创建时执行一次。当你首次创建数据库时,系统会调用这个方法来创建所有必要的表和初始化数据库结构。如果数据库已经存在,onCreate将不会被再次调用

5、SQLiteDatabase类的insert方法说明
insert方法说明
public long insert(String table, String nullColumnHack, ContentValues values)
执行插入记录动作,该语句返回插入记录的行号

参数说明:
(1)table:表名
(2)nullColumnHack:作用是如果第三个参数ContentValues为空,则没有字段插入。所以这里要指定一个字段设置为NULL
(3)values:键值对
返回值:
返回行的rowID,如果返回-1则添加失败

delete方法说明
public int delete(String table, String whereClause, String[] whereArgs)

参数说明:
(1)table:表名
(2)whereClause:where条件字段
(3)whereArgs:where传入的参数
返回值:
返回影响的行数

update方法说明
public int update(String table, ContentValues values, String whereClause, String[] whereArgs)

参数说明:
(1)table:表名
(2)values:
(3)whereClause:where条件字段
(4)whereArgs:where传入的参数
返回值:
返回影响的行数

query方法说明
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

参数说明:
(1)table:表名
(2)columns:列名
(3)selection:选项
(4)selectionArgs:选项参数
(5)groupBy:groupBy参数
(6)having:having参数
(7)orderBy:orderBy参数
返回值:
返回结果集的游标

6、例子
数据库工具类UserDBHelper.java

package com.example.chapter06.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

import com.example.chapter06.entity.User;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class UserDBHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "user.db";
    private static final String TABLE_NAME = "user_info";
    private static final int DB_VERSION = 1;
    private static UserDBHelper mHelper = null;
    private SQLiteDatabase mRDB = null;
    private SQLiteDatabase mWDB = null;

    private UserDBHelper(@Nullable Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    // 利用单例模式获取数据库帮助器的唯一实例
    public static UserDBHelper getInstance(Context context) {
        if (mHelper == null) {
            mHelper = new UserDBHelper(context);
        }
        return mHelper;
    }

    // 打开数据库的读连接
    public SQLiteDatabase openReadLink() {
        if (mRDB == null || !mRDB.isOpen()) {
            mRDB = mHelper.getReadableDatabase();
        }
        return mRDB;
    }

    // 打开数据库的写连接
    public SQLiteDatabase openWriteLink() {
        if (mWDB == null || !mWDB.isOpen()) {
            mWDB = mHelper.getWritableDatabase();
        }
        return mWDB;
    }

    // 关闭数据库连接
    public void closeLink() {
        if (mRDB != null) {
            mRDB.close();
            mRDB = null;
        }

        if (mWDB != null) {
            mWDB.close();
            mWDB = null;
        }
    }

    // 创建数据库,执行建表语句
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                "name VARCHAR NOT NULL," +
                "age INTEGER NOT NULL," +
                "height FLOAT NOT NULL," +
                "weight FLOAT NOT NULL," +
                "married INTEGER NOT NULL," +
                "update_time VARCHAR NOT NULL);";
        sqLiteDatabase.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }

    public long insert(User user) {
        ContentValues values = new ContentValues();
        values.put("name", user.getName());
        values.put("age", user.getAge());
        values.put("height", user.getHeight());
        values.put("weight", user.getWeight());
        values.put("married", user.isMarried());
        values.put("update_time", LocalDateTime.now().toString());

        return mWDB.insert(TABLE_NAME, null, values);
    }

    public int deleteByName(String name) {
        return mWDB.delete(TABLE_NAME, "name=?", new String[]{name});
    }

    public int update(User user) {
        ContentValues values = new ContentValues();
        if (user.getAge() > 0) {
            values.put("age", user.getAge());
        }
        if (user.getHeight() > 0f) {
            values.put("height", user.getHeight());
        }
        if (user.getWeight() > 0f) {
            values.put("weight", user.getWeight());
        }
        values.put("married", user.isMarried());
        values.put("update_time", LocalDateTime.now().toString());
        return mWDB.update(TABLE_NAME, values, "name=?", new String[]{user.getName()});
    }

    public List<User> queryAll() {
        List<User> list = new ArrayList<>();
        // 执行记录查询,返回结果集的游标
        Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null);
        // 循环取出游标指向的每条记录
        while (cursor.moveToNext()) {
            User user = new User(
                    cursor.getInt(0),
                    cursor.getString(1),
                    cursor.getInt(2),
                    cursor.getFloat(3),
                    cursor.getFloat(4),
                    // SQLite没有布尔类型,用0表示false,用1表示true
                    cursor.getInt(5) == 1
            );
            list.add(user);
        }
        cursor.close();

        return list;
    }
}

实体类User.java

package com.example.chapter06.entity;

import androidx.annotation.NonNull;

public class User {
    private int id; // 序号
    private String name; // 姓名
    private int age; // 年龄
    private float height; // 升高
    private float weight; // 体重
    private boolean married; // 婚否

    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;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    public boolean isMarried() {
        return married;
    }

    public void setMarried(boolean married) {
        this.married = married;
    }

    public User(String name, int age, float height, float weight, boolean married) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
        this.married = married;
    }

    public User(int id, String name, int age, float height, float weight, boolean married) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
        this.married = married;
    }

    @NonNull
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                ", weight=" + weight +
                ", married=" + married +
                '}';
    }
}

布局文件activity_sqlite_helper.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SQLiteHelperActivity">

    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="2"
        android:rowCount="4">

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="姓名:"
            android:textSize="17sp"/>

        <EditText
            android:id="@+id/et_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:inputType="text"
            android:hint="请输入姓名"/>

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="年龄:"
            android:textSize="17sp"/>

        <EditText
            android:id="@+id/et_age"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:inputType="number"
            android:maxLength="3"
            android:hint="请输入年龄"/>

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="身高:"
            android:textSize="17sp"/>

        <EditText
            android:id="@+id/et_height"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:inputType="numberDecimal"
            android:maxLength="6"
            android:hint="请输入身高"/>

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="体重:"
            android:textSize="17sp"/>

        <EditText
            android:id="@+id/et_weight"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:inputType="numberDecimal"
            android:maxLength="6"
            android:hint="请输入体重"/>

    </GridLayout>

    <CheckBox
        android:id="@+id/ck_married"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="已婚"
        android:textSize="17sp"/>

    <Button
        android:id="@+id/btn_save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加"
        android:textSize="17sp"/>

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="删除"
        android:textSize="17sp"/>

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="修改"
        android:textSize="17sp"/>

    <Button
        android:id="@+id/btn_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询"
        android:textSize="17sp"/>

</LinearLayout>

SQLiteHelperActivity.java

package com.example.chapter06;

import androidx.appcompat.app.AppCompatActivity;

import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;

import com.example.chapter06.database.UserDBHelper;
import com.example.chapter06.entity.User;
import com.example.chapter06.util.ToastUtil;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class SQLiteHelperActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText et_name;
    private EditText et_age;
    private EditText et_height;
    private EditText et_weight;
    private CheckBox ck_married;
    private UserDBHelper mHelper;
    private SQLiteDatabase mWDB;
    private SQLiteDatabase mRDB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite_helper);

        et_name = findViewById(R.id.et_name);
        et_age = findViewById(R.id.et_age);
        et_height = findViewById(R.id.et_height);
        et_weight = findViewById(R.id.et_weight);
        ck_married = findViewById(R.id.ck_married);

        findViewById(R.id.btn_save).setOnClickListener(this);
        findViewById(R.id.btn_delete).setOnClickListener(this);
        findViewById(R.id.btn_update).setOnClickListener(this);
        findViewById(R.id.btn_query).setOnClickListener(this);

    }

    // onCreate执行后,执行onStart
    @Override
    protected void onStart() {
        super.onStart();
        // 获得数据库帮助器的实例
        mHelper = UserDBHelper.getInstance(this);
        // 打开数据库帮助器的读写连接
        mWDB = mHelper.openWriteLink();
        mRDB = mHelper.openReadLink();
    }

    // 界面不可见时,退出到后台时执行
    @Override
    protected void onStop() {
        super.onStop();
        // 关闭数据库连接
        mHelper.closeLink();
    }

    @Override
    public void onClick(View view) {
        String name = et_name.getText().toString();
        if (TextUtils.isEmpty(name)) {
            name = "";
        }
        String age = et_age.getText().toString();
        if (TextUtils.isEmpty(age)) {
            age = "0";
        }
        String height = et_height.getText().toString();
        if (TextUtils.isEmpty(height)) {
            height = "0";
        }
        String weight = et_weight.getText().toString();
        if (TextUtils.isEmpty(weight)) {
            weight = "0";
        }
        User user = null;
        if (view.getId() == R.id.btn_save) {
            user = new User(name,
                    Integer.parseInt(age),
                    Float.parseFloat(height),
                    Float.parseFloat(weight),
                    ck_married.isChecked());

            if (mHelper.insert(user) > 0) {
                ToastUtil.show(this, "添加成功");
            }

        } else if (view.getId() == R.id.btn_delete) {
            if (mHelper.deleteByName(name) > 0) {
                ToastUtil.show(this, "删除成功");
            } else {
                ToastUtil.show(this, "记录不存在");
            }

        } else if (view.getId() == R.id.btn_update) {
            user = new User(name,
                    Integer.parseInt(age),
                    Float.parseFloat(height),
                    Float.parseFloat(weight),
                    ck_married.isChecked());

            int i = mHelper.update(user);
            ToastUtil.show(this, "更新行数:" + i);

        } else if (view.getId() == R.id.btn_query) {
            List<User> users = mHelper.queryAll();
            for (User u : users) {
                Log.d("sam", u.toString());
            }
        }
    }
}

工具类ToastUtil.java,显示短的提示条

package com.example.chapter06.util;

import android.content.Context;
import android.widget.Toast;

public class ToastUtil {

    public static void show(Context ctx, String message) {
        Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show();
    }
}

7、用Android Studio自带工具查看表结构
左上角View -> Tool Windows -> App Inspection,选Database Inspector

三、事务管理

1、例子

try {
	mWDB.beginTransaction();
	mWDB.insert(TABLE_NAME1, null, values1);
	mWDB.insert(TABLE_NAME2, null, values2);
	mWDB.setTransactionSuccessful();
} catch (Exception e) {
	e.printStackTrace();
} finally {
	mWDB.endTransaction();
}

四、数据库版本升级

1、如果后续程序升级,表结构要加字段,要修改onUpgrade方法,把定义的DB_VERSION加1
这样就会触发执行onUpgrade方法。触发条件就是DB_VERSION变量发生变化了

2、例子
private static final int DB_VERSION = 2;

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        String sql = "alter table " + TABLE_NAME + " add column phone varchar;";
        sqLiteDatabase.execSQL(sql);
        sql = "alter table " + TABLE_NAME + " add column password varchar;";
        sqLiteDatabase.execSQL(sql);
    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值