Android手把手编写儿童手机远程监控App之SQLite详解2

概述

上节完成嘟宝SQLite数据库功能。SQLite 是一个嵌入式关系型数据库管理系统,与传统数据库(如 MySQL、PostgreSQL)不同,它不是一个独立的进程,而是一个可以直接嵌入到应用程序文件性数据库。是全球部署最广泛的数据库引擎,因为它在简单性、可靠性和功能性之间取得了很好的平衡。如果你需要一个轻量级、零配置、可靠的数据存储解决方案,SQLite 是非常好的选择。

SQLite数据类型不多,简单够用。

  • INTEGER数字类型
  • REAL浮点型
  • TEXT文本型
  • BLOB二进制文件类型 SQLiteOpenHelper类是Android 用于管理SQLite数据库。包括数据库的创建、数据的增删改查、事物等等。在 Android 中使用原始 SQL 语句操作 SQLite 数据库,相比使用 ORM 框架(如 Room)或 Android 封装的 API,有以下显著好处:
  • 完全的控制权
  • 执行复杂查询更高效
  • 性能优势明显
  • 迁移和维护简单
  • 调试和排查问题方便
  • 避免 ORM 的陷阱

基于原始SQL增删改查

表结构: id 主键、自增、不为空 dumaName 嘟妈名称 dumaId嘟妈身份识别码 bindDateTime嘟妈绑定时间 核心函数

  • rawQuery 用于原始SQL查询功能
  • execSQL用于原始SQL增删改、表格创建等
clike 复制代码
Cursor rawQuery(String sql, String[] selectionArgs)
Cursor cursor = db.rawQuery("SELECT * FROM users WHERE age > ? AND name LIKE ?", new Object[]{"18", "%张%"});

rawQuery只要不抛出SQLException 异常,代表执行成功,他的返回查询结果是Cursor 。selectionArgs是占位符,它将Object内的结构分配给SQL语句中的问号。实际生成的SQL语句

clike 复制代码
SELECT * FROM users WHERE age > 18 AND name LIKE "18"
clike 复制代码
void execSQL(String sql, Object[] bindArgs)
db.execSQL("INSERT INTO users (name, age) VALUES (?, ?)", 
           new Object[]{"张三", 25});

execSQL不返回值,只要不抛出SQLException 异常,代表执行成功。bindArgs是占位符,它将Object内的结构分配给SQL语句中的问号,实际生成的语句

clike 复制代码
INSERT INTO users (name, age) VALUES ("张三", 25)

我们可以使用字符串拼接的方式,取消占位符的使用,将其设置NULL即可或者不传递。

事例

MyDB类

clike 复制代码
package com.zilong.dubao;

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

public class MyDB extends SQLiteOpenHelper {
    public MyDB( String name, SQLiteDatabase.CursorFactory factory,
                int version){
        super(app.getContext(), name, factory, version);


    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        Toast.makeText(app.getContext(),"数据库与表创建成功",Toast.LENGTH_SHORT).show();
        String dumaTabel="CREATE TABLE duma (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, dumaName text,dumaId text,bindDateTime INTEGER)";
        db.execSQL(dumaTabel);
    }

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

    }
}

MainActivity类源码

clike 复制代码
package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,12);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();
//        startService();
        ImageView qrCodeImageView = findViewById(R.id.qrCode);
        uuid u=new uuid();
        String dubaoId=u.getuuid();
        Log.d("uuid",dubaoId);
        Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
        int foreground = Color.parseColor("#2196F3"); // 前景蓝
        int background = Color.WHITE; // 背景白
        Bitmap qrBitmap = QRCodeUtil.ShowQRCode(
                dubaoId, logoBitmap, 0.2f, foreground, background);
        qrCodeImageView.setImageBitmap(qrBitmap);
    }
    private void initBtn(){
        Button createDBBtn=findViewById(R.id.createDB);
        createDBBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDB.getWritableDatabase();

            }
        });
        Button insertBtn=findViewById(R.id.insertDB);
        insertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                String sql="";
                sql=String.format("INSERT INTO duma( \"dumaName\", \"dumaId\", \"bindDateTime\") VALUES ( '%s', '%s', '%d');","嘟妈","f1122aeb-f2b0-400d-9919-eddd2eaebaa2" ,System.currentTimeMillis());
                Log.d("mqtt",sql);
                db.execSQL(sql);

            }
        });
        Button updateBtn=findViewById(R.id.updateDB);
        updateBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                String sql="";
                sql=String.format("UPDATE duma set dumaName=\"%s\" WHERE dumaId=\"%s\"","嘟妈2","f1122aeb-f2b0-400d-9919-eddd2eaebaa2" );
                Log.d("mqtt",sql);
                db.execSQL(sql);

            }
        });

        Button queryBtn=findViewById(R.id.queryDB);
        queryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                Cursor cursor = db.rawQuery("SELECT * FROM duma", null);
                if (cursor.moveToFirst()){
                    do{
                        @SuppressLint("Range") String dumaName=cursor.getString(cursor.getColumnIndex("dumaName"));
                        @SuppressLint("Range") String dumaId=cursor.getString(cursor.getColumnIndex("dumaId"));
                        @SuppressLint("Range") int bindDateTime=cursor.getInt(cursor.getColumnIndex("bindDateTime"));
                        Toast.makeText(MainActivity.this,dumaName,Toast.LENGTH_SHORT).show();

                    }while (cursor.moveToNext());
                }
                cursor.close();



            }

        });
        Button delBtn=findViewById(R.id.delDB);
        delBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db =myDB.getWritableDatabase();
                String sql="";
                sql=String.format("DELETE FROM duma WHERE dumaId=\"%s\"","f1122aeb-f2b0-400d-9919-eddd2eaebaa2");
                Log.d("mqtt",sql);
                db.execSQL(sql);

            }
        });


    }

    private void startService(){
        Intent i = new Intent(this, MyService.class);
        startForegroundService(i);
    }


}

运行实例查看结果 点击创建数据库两次,但实际onCreate只调用一次创建。 分别操作

  • 插入数据-查询数据
  • 更新数据-查询数据
  • 删除数据-查询数据

SQLite 事务

在 Android SQLite 中,事务是一组数据库操作的逻辑单元,要么全部执行成功,要么全部失败回滚,确保数据的一致性和完整性。 事务的基本特性(ACID)

  • 原子性:事务中的所有操作要么全部成功,要么全部失败
  • 一致性:事务执行前后数据库保持完整状态
  • 隔离性:并发事务之间互不干扰
  • 持久性:事务提交后数据永久保存
clike 复制代码
package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private MyDB myDB=new MyDB("dubao.db",null,12);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBtn();
    }
    private void initBtn(){
        Button rollupBtn=findViewById(R.id.rollupDB);
        rollupBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = myDB.getWritableDatabase();
                db.beginTransaction();
                try {
                    // 执行多个数据库操作
                    for (int i = 0; i < 3; i++) {
                        String sql="";
                        sql=String.format("INSERT INTO duma( \"dumaName\", \"dumaId\", \"bindDateTime\") VALUES ( '%s', '%s', '%d');","嘟妈"+i,"f1122aeb-f2b0-400d-9919-eddd2eaebaa2" ,System.currentTimeMillis());
                        db.execSQL(sql);
                        if (i==1){
                            throw  new Exception("失败");
                        }
                    }
                    db.setTransactionSuccessful();
                    db.close();


                } catch (Exception e) {
                    // 发生异常,自动回滚
                    e.printStackTrace();
                    db.endTransaction();
                    db.close();
                    Toast.makeText(MainActivity.this,"发生异常,自动回滚",Toast.LENGTH_SHORT).show();
                }

            }
        }); 
    }  
}

运行效果查看

相关推荐
-SOLO-2 小时前
Python 爬取小红书 文章标题和内容 仅供学习
android·python·学习
ooseabiscuit2 小时前
Laravel5
android·php·laravel
科技道人3 小时前
Android 禁止使用ipv6 测试
android·禁用ipv6
AlexMaybeBot3 小时前
巧用 OpenClaw 为 Android 开发电脑瘦身
android·github·ai编程
pengyu7 小时前
【Kotlin 协程修仙录 · 金丹境 · 中阶】 | 启动密法:CoroutineStart 四种模式与底层调度玄机
android·kotlin
Android小码家7 小时前
Xposed之雷电5+Android 7.1.2 Xposed 89(古早安装)
android·xposed
ooseabiscuit7 小时前
Laravel2.x核心特性全解析
android
UXbot7 小时前
AI一次生成iOS和Android双端原型功能详解
android·前端·ios·kotlin·交互·swift
YF02118 小时前
基于 CRNN 与 ML Kit 的高性能移动端扫描技术方案
android·aigc