Android SQLite存储
1、 引言
Android 中的 SQLite 是一种轻量级、嵌入式的关系型数据库,专为资源受限的设备(如智能手机和平板)设计。它被深度集成在 Android 系统中,是官方推荐用于本地结构化数据持久化的方案之一。
2、 核心特点
-
无服务端架构:SQLite 不需要独立的数据库服务器,数据库以单个
.db文件形式存储在应用私有目录中。 -
轻量高效:内存占用仅数百 KB,适合移动设备。
-
标准 SQL 支持:支持大部分 SQL 语法(如
SELECT,INSERT,UPDATE,DELETE,CREATE TABLE等)。 -
数据类型灵活:支持
NULL(空值)、INTEGER(整数)、REAL(浮点数)、TEXT(字符串)、BLOB(大数据),且具备动态类型系统和隐式类型转换。 -
安全隔离:数据库文件默认存储在
/data/data/<包名>/databases/下,其他应用无法直接访问(除非 root )。
3、Android 操作 SQLite 的核心类
在 Android 开发中使用 SQLite 数据库,有三个核心类是我们需要深入了解和熟练掌握的,它们分别是 SQLiteOpenHelper、SQLiteDatabase和 Cursor。这三个类在 SQLite 数据库的操作过程中各自有着独特的作用和使用场景。
-
SQLiteOpenHelper:是一个非常重要的辅助类,它主要负责管理数据库的创建和版本更新。当我们的应用需要创建一个 SQLite 数据库时,通常会创建一个类继承自 SQLiteOpenHelper,并在这个类中重写 onCreate 和 onUpgrade 方法。onCreate 方法在数据库首次创建时被调用,我们可以在这个方法中编写创建数据库表结构的 SQL 语句。而 onUpgrade 方法则在数据库版本发生变化时被调用,比如我们需要添加新的表字段、修改表结构或者删除旧表时,就可以在这个方法中实现相应的逻辑。 -
SQLiteDatabase:是操作 SQLite 数据库的核心类,它就像是一个万能的数据库操作工具,封装了大量用于操作数据库的 API。通过这些 API,我们可以轻松地对数据库进行各种操作,比如执行 SQL 语句(无论是简单的查询、插入,还是复杂的创建表、删除表等操作)。它提供了如 insert、delete、update、query 等方法,这些方法使得我们能够方便地进行数据的增、删、改、查操作。 -
Cursor:是用于遍历查询结果集的工具。当我们执行一个查询操作(如使用 SQLiteDatabase 的 query 或 rawQuery 方法)后,会返回一个 Cursor 对象,这个对象就像是一个指向查询结果集的游标。我们可以通过它提供的一系列方法(如 moveToFirst、moveToNext、getInt、getString 等)来逐行读取和获取结果集中的数据。务必在使用后关闭,避免内存泄漏。
4、创建数据库和表
在 Android 中创建 SQLite 数据库,通常的做法是创建一个类继承自 SQLiteOpenHelper 类,然后重写其中的 onCreate 和 onUpgrade 方法。这两个方法在数据库的创建和版本管理过程中起着至关重要的作用。
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "APPLogs.db";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 首次创建数据库时调用
String CREATE_TABLE = "CREATE TABLE logs (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"http_status INTEGER," +
"create_time TEXT NOT NULL)";
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 当数据库版本发生变化时,先删除旧表,再重新创建新表
db.execSQL("DROP TABLE IF EXISTS logs");
onCreate(db);
}
}
5、基本操作
在创建好数据库和表之后,我们就需要对其中的数据进行各种操作,最常见的就是增(Create)、查(Read)、改(Update)、删(Delete)操作,简称 CRUD 操作。
- 插入数据
在 Android 中,向 SQLite 数据库插入数据有两种常见的方式,一种是使用 insert 方法,另一种是使用 execSQL 方法。
// 方法1:使用ContentValues
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("id", 1);
values.put("http_status", 2);
values.put("create_time", "2026-01-01");
//把数据插入到数据库中,返回当前行的id,若为-1则数据插入失败
long newRowId = db.insert("logs", null, values);
// 方法2:使用execSQL
db.execSQL("INSERT INTO logs (id, http_status, create_time) VALUES (?, ?, ?)",
new Object[]{0, 1, "2026-01-01"});
- 查询数据
在 SQLite 数据库中查询数据,我们主要使用 query 和 rawQuery 方法。这两个方法都用于执行查询操作,但在使用方式上略有不同。
query 方法是一种较为便捷的查询方式,它的参数较多,可以通过这些参数来指定查询的表名、要查询的列、查询条件、条件参数、分组方式、过滤条件和排序方式等。
rawQuery 方法则更加灵活,它允许我们直接编写 SQL 查询语句。方法的第一个参数是 SQL 查询语句,第二个参数是查询条件的参数数组(如果没有条件参数,可以设为 null)。这种方式适用于一些复杂的查询场景,比如多表联合查询等。
无论是使用 query 方法还是 rawQuery 方法,在查询操作完成后,都要记得关闭 Cursor 和数据库连接,以释放资源,避免内存泄漏。
// 方法1:使用query()方法
SQLiteDatabase db = dbHelper.getReadableDatabase();
// query参数依次为:表名、要查询的列、WHERE条件、WHERE参数、GROUP BY、HAVING、ORDER BY
Cursor cursor = db.query("logs", null, null,null, null, null, null);
try {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndexOrThrow("id"));
String http_status = cursor.getInt
(cursor.getColumnIndexOrThrow("http_status"));
String create_time = cursor.getString(cursor.getColumnIndexOrThrow("create_time"));
// 处理数据...
}
} finally {
cursor.close(); // 重要:必须关闭Cursor
}
// 方法2:使用rawQuery()
Cursor cursor = db.rawQuery("SELECT * FROM logs", null);
-
更新数据
在 SQLite 数据库中更新数据,我们主要使用 update 方法。update 方法可以根据指定的条件,对表中的数据进行更新。如果更新成功,update 方法会返回受影响的行数;如果更新失败,会返回 0。
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("create_time", "2026-01-02");
// 参数依次为:表名、更新内容、WHERE条件、WHERE参数
int count = db.update("logs", values,
"create_time = ?",
new String[] {"2026-01-01"});
-
删除数据
在 SQLite 数据库中删除数据,我们使用 delete 方法。delete 方法可以根据指定的条件,从表中删除数据。如果删除成功,delete 方法会返回受影响的行数;如果删除失败,会返回 0。
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 参数依次为:表名、WHERE条件、WHERE参数
int deletedRows = db.delete("logs", "id = ?", new String[] {String.valueOf(rowId)});
-
事务处理
事务是数据库操作中的一个重要概念,它可以将一组相关的数据库操作组合在一起,确保这些操作要么全部成功执行,要么一个都不执行(即全部回滚到未执行的状态),这被称为事务的原子性。事务的作用主要体现在两个方面:保障数据的一致性和提高执行性能。
在批量数据操作时,事务还能显著提高执行性能。默认情况下,SQLite 会为每个插入、更新或删除操作开启一个隐式事务并立即提交,这意味着如果我们要进行多次这样的操作,就会频繁地进行磁盘 I/O 操作,因为每次提交事务都可能涉及到磁盘的写入。而当我们将多次操作放在一个手动的事务中时,这些操作会被暂时缓存,直到事务结束时才一次性提交,这样可以大大减少磁盘 I/O 的次数,从而提高性能。
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 开启一个事务
db.beginTransaction();
try {
// 执行多个操作
ContentValues values1 = new ContentValues();
values.put("id", 2);
values.put("http_status", 2);
values.put("create_time", "2026-01-02");
db.insert("logs", null, values);
ContentValues values2 = new ContentValues();
values.put("id", 3);
values.put("http_status", 3);
values.put("create_time", "2026-01-03");
db.insert("logs", null, values2);
db.setTransactionSuccessful(); // 标记事务成功
} catch (Exception e) {
// 事务失败会自动回滚
e.printStackTrace();
} finally {
db.endTransaction(); // 结束事务
}
6、实际使用示例
package com.sqlitelibrary;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
public class SQLiteOpenHelperManage extends SQLiteOpenHelper {
public SQLiteOpenHelperManage(Context context, String filename, String dbName, int version){
super(context, getDatabasePath(filename, dbName), null, version);
}
/**
* 获取数据库路径
* @param dbName
* @return
*/
private static String getDatabasePath(String filename, String dbName) {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.d("SD卡不可用", "");
return null;
}
File publicDir = new File(Environment.getExternalStorageDirectory(), filename);
if (!publicDir.exists()) {
boolean isMkdirs = publicDir.mkdirs();
Log.d("mkdirs", "isMkdirs: " + isMkdirs);
}
String path = publicDir.getAbsolutePath();
// 使用这个路径来创建或访问数据库文件
File dbFile = new File(path, dbName + ".db");
if (!dbFile.exists()) {
try {
boolean isCreateNewFile = dbFile.createNewFile();
Log.d("createNewFile", "isCreateNewFile: " + isCreateNewFile);
} catch (IOException e) {
e.printStackTrace();
}
}
return dbFile.getAbsolutePath();
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// 首次创建数据库时调用,用于建表
}
// 更新数据库表与数据库表字段
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
// 数据库版本升级时调用,通常用于表结构变更
}
/**
* 创建数据库表
* @param sql
* @return
*/
public String createTable (String sql) {
try {
SQLiteDatabase db = getWritableDatabase();
db.execSQL(sql);
return "创建成功";
} catch (SQLiteException e) {
return e.getMessage();
} catch (Exception e) {
return e.getMessage();
}
}
/**
* 执行sql语句
* @param sql
* @return
*/
public String executeSql(String sql){
try {
SQLiteDatabase db = getWritableDatabase();
db.execSQL(sql);
return "执行成功";
} catch (SQLiteException e) {
return e.getMessage();
} catch (Exception e) {
return e.getMessage();
}
}
/**
* 查询数据
* @param sql
* @return
*/
public String selectSql(String sql) {
JSONArray resultSet = new JSONArray();
try {
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.rawQuery(sql, null);
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
int totalColumn = cursor.getColumnCount();
JSONObject rowObject = new JSONObject();
for(int i=0 ; i< totalColumn ; i++) {
if(cursor.getColumnName(i) != null) {
try {
if(cursor.getString(i) != null) {
rowObject.put(cursor.getColumnName(i), cursor.getString(i));
} else {
rowObject.put(cursor.getColumnName(i), "");
}
} catch (Exception e) {
// Log.d("userTable", e.getMessage() );
}
}
}
resultSet.put(rowObject);
cursor.moveToNext();
}
cursor.close();
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
Log.d("查询数据结果", "JSONArray: " + resultSet);
Log.d("查询数据结果", "toString: " + resultSet.toString());
return resultSet.toString();
}
/**
* 判断数据库是否打开
*/
public boolean isOpenDatabase() {
try {
SQLiteDatabase db = getWritableDatabase();
return db.isOpen();
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
/**
* 关闭数据库
*/
public boolean closeDatabase() {
try {
SQLiteDatabase db = getWritableDatabase();
db.close();
return true;
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
/**
* 开启事务
*/
public boolean beginTransaction() {
try {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
return true;
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
/**
* 设置事务标志为成功,当结束事务时就会提交事务
*/
public boolean setTransactionSuc() {
try {
SQLiteDatabase db = getWritableDatabase();
db.setTransactionSuccessful();
return true;
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
/**
* 结束事务
*/
public boolean endTransaction() {
try {
SQLiteDatabase db = getWritableDatabase();
db.endTransaction();
return true;
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
/**
* 设置数据库版本
*/
public boolean setDatabaseVersion(int version) {
try {
SQLiteDatabase db = getWritableDatabase();
db.setVersion(version);
return true;
} catch (SQLiteException e) {
Log.e("数据库异常", "SQLiteException: " + e.getMessage());
} catch (Exception e) {
Log.e("数据库异常", "Exception: " + e.getMessage());
}
return false;
}
}
7、注意事项
-
数据库文件位置:
/data/data/<包名>/databases/。 -
数据库文件大小限制:理论上最大 140TB,但实际受设备存储限制。
-
并发访问:SQLite支持多线程读,但写操作需要同步。
-
数据类型:SQLite是动态类型,但建议按声明类型存储。
8、总结
SQLite 是一种轻量级的开源数据库框架,已经被预置到 Android 系统中,我们可以非常方便的使用。既可以通过标准的 SQL 语句进行操作,也可以使用Android 提供的 Java 接口做 CURD。无论选择哪种操作方式,都要注意数据库操作应在后台线程执行,并正确处理数据库的创建、升级和资源释放。
更多推荐



所有评论(0)