概述
上节完成嘟宝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();
}
}
});
}
}
运行效果查看 