当前位置:首页 > 行业动态 > 正文

安卓开发之sqlite数据库

SQLite数据库简介

Android内置了SQLite数据库,支持轻量级本地数据存储,适用于:

  • 离线数据缓存
  • 用户配置保存
  • 小规模数据管理

核心类SQLiteDatabase(操作数据库)、SQLiteOpenHelper(管理数据库创建与升级)

安卓开发之sqlite数据库  第1张


创建与初始化数据库

定义SQLiteOpenHelper子类

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "app_data.db";
    private static final int DATABASE_VERSION = 1;
    public MyDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        // 创建表语句
        String sql = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)";
        db.execSQL(sql);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 升级时删除旧表并创建新表(慎用!需考虑数据迁移)
        db.execSQL("DROP TABLE IF EXISTS users");
        onCreate(db);
    }
}

获取数据库实例

MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase(); // 读写权限
// 或 getReadableDatabase() 仅读权限

基本数据库操作

插入数据

ContentValues values = new ContentValues();
values.put("name", "Alice");
values.put("age", 25);
long rowId = db.insert("users", null, values); // 返回插入行的ID

查询数据

// 查询所有用户
Cursor cursor = db.query("users", null, null, null, null, null, null);
while (cursor.moveToNext()) {
    int id = cursor.getInt(cursor.getColumnIndex("id"));
    String name = cursor.getString(cursor.getColumnIndex("name"));
    int age = cursor.getInt(cursor.getColumnIndex("age"));
    // 处理数据...
}
cursor.close(); // 必须关闭游标

更新数据

ContentValues values = new ContentValues();
values.put("age", 26);
int rowsAffected = db.update("users", values, "name=?", new String[]{"Alice"});

删除数据

int rowsDeleted = db.delete("users", "age < ?", new String[]{"20"}); // 删除年龄小于20的用户

数据库升级与迁移

版本号管理

  • DATABASE_VERSION用于标识数据库结构版本
  • 每次结构变更需递增版本号,并在onUpgrade中处理迁移逻辑

数据迁移策略(示例)

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < 2) {
        // 添加新字段
        db.execSQL("ALTER TABLE users ADD COLUMN email TEXT");
    }
    if (oldVersion < 3) {
        // 复杂迁移:创建临时表 → 数据复制 → 替换旧表
    }
}

异步操作与线程安全

主线程禁止数据库操作

Android从API 11开始禁止在主线程执行数据库读写,否则抛NetworkOnMainThreadException
解决方案

  • AsyncTask(已过时,建议用其他方式)
  • ExecutorService
  • LiveData + ViewModel(架构组件)
  • Kotlin协程(推荐)

Kotlin协程示例

GlobalScope.launch(Dispatchers.IO) {
    val db = dbHelper.writableDatabase
    db.insert("users", null, mapOf("name" to "Bob", "age" to 30))
    // 其他操作...
}

常见问题与优化

问题 解决方案
多线程并发访问冲突 使用synchronizedSQLiteDatabase.acquireLock(),推荐通过单例模式管理SQLiteOpenHelper
内存泄漏 避免长时间持有SQLiteDatabase引用,及时关闭Cursor
大数据量查询性能差 分页查询(LIMIT + OFFSET)、索引优化(CREATE INDEX
敏感数据存储安全 使用SQLCipher加密数据库,或AES加密后存储

相关问题与解答

问题1:如何将SQLite数据库迁移到Room持久库?

解答
Room是Android官方推荐的抽象层,提供更简洁的API和编译时校验,迁移步骤:

  1. 定义@Entity实体类映射表结构
  2. 创建@Dao接口定义增删改查方法
  3. 通过Room.databaseBuilder()构建数据库实例
  4. 迁移原有SQLite逻辑到Room(需处理版本升级)
    优势:类型安全、支持LiveData、RxJava、协程。

问题2:SQLite支持事务吗?如何保证原子性?

解答

  • 支持事务,通过beginTransaction()setTransactionSuccessful()实现
  • 示例:
    db.beginTransaction();
    try {
      db.insert(...);
      db.update(...);
      db.setTransactionSuccessful(); // 标记成功
    } finally {
      db.endTransaction(); // 提交或回滚
    }
  • 事务可确保多条操作要么全部成功,要么全部撤销
0