上一篇
安卓开发如何查询数据库
- 行业动态
- 2025-04-22
- 8
安卓开发中查询数据库的实现方式
使用 SQLite 直接查询
SQLite 是安卓内置的轻量级数据库,适合简单场景。
步骤:
- 创建数据库帮助类
通过SQLiteOpenHelper
管理数据库创建与版本更新。 - 获取可读实例
调用getReadableDatabase()
获取可读数据库对象。 - 执行查询
使用rawQuery()
或query()
方法执行 SQL 语句。
代码示例:
// 数据库帮助类 public class MyDatabaseHelper extends SQLiteOpenHelper { public MyDatabaseHelper(Context context) { super(context, "my_database.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE user (id INTEGER PRIMARY KEY, name TEXT)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS user"); onCreate(db); } } // 查询数据 MyDatabaseHelper dbHelper = new MyDatabaseHelper(context); SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT FROM user WHERE id = ?", new String[]{"1"}); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); // 处理数据 } cursor.close(); db.close();
优点:
- 直接操作,灵活性高。
缺点: - 需手动处理线程安全、SQL 注入风险、数据转换。
使用 Room 持久化库(推荐)
Room 是安卓官方推荐的数据库层封装,基于 SQLite,提供抽象层和编译时校验。
步骤:
- 定义实体类
使用@Entity
标注对应数据库表。 - 创建 DAO 接口
定义@Query
方法或增删改查方法。 - 构建数据库类
继承RoomDatabase
并绑定实体。 - 调用查询方法
通过 DAO 实例执行查询。
代码示例:
// 实体类 @Entity(tableName = "user") public class User { @PrimaryKey(autoGenerate = true) public int id; @ColumnInfo(name = "name") public String name; } // DAO 接口 @Dao public interface UserDao { @Query("SELECT FROM user WHERE id = :userId") User getUserById(int userId); } // 数据库类 @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } // 查询数据(需在子线程或异步执行) AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "app_db").build(); User user = db.userDao().getUserById(1);
优点:
- 编译时 SQL 校验,避免运行时错误。
- 支持 LiveData 实时监听、类型安全。
缺点: - 学习成本稍高,需理解注解和架构。
通过 ContentProvider 查询(跨应用)
ContentProvider 用于公开数据给其他应用,适合数据共享场景。
步骤:
- 创建 ContentProvider
实现query()
方法处理查询请求。 - 调用
ContentResolver
查询
使用query()
方法发送查询请求。
代码示例:
// ContentProvider 中处理查询 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); return db.query("user", projection, selection, selectionArgs, null, null, sortOrder); } // 客户端查询 Uri uri = Uri.parse("content://com.example.app.provider/user"); Cursor cursor = getContentResolver().query(uri, null, "id=?", new String[]{"1"}, null); if (cursor != null) { while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); // 处理数据 } cursor.close(); }
优点:
- 支持跨应用数据共享。
缺点: - 实现复杂,需处理权限和数据暴露。
查询网络数据库(如 Firebase)
若数据存储在远程数据库(如 Firebase Realtime Database),需通过 API 查询。
步骤:
- 添加依赖
引入 Firebase SDK。 - 初始化数据库
获取FirebaseDatabase
实例。 - 监听数据
使用addValueEventListener
或addListenerForSingleValueEvent
。
代码示例:
// Firebase 查询 FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("users").child("1"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { String name = dataSnapshot.child("name").getValue(String.class); // 处理数据 } @Override public void onCancelled(DatabaseError error) {} });
注意事项
问题 | 解决方案 |
---|---|
主线程操作数据库 | 使用 AsyncTask 、ExecutorService 或 LiveData (Room)在子线程执行查询。 |
SQL 注入风险 | 使用参数化查询()或 Room 的 @Query 参数绑定。 |
数据库版本升级 | 实现 Migration 接口或覆盖 onUpgrade() 方法处理数据迁移。 |
权限问题 | 安卓 10+ 需申请 READ_EXTERNAL_STORAGE (若存储在外部存储)。 |
相关问题与解答
问题1:如何实现 Room 数据库的版本迁移?
解答:
在 Room.databaseBuilder()
中添加 .addMigrations(MIGRATION_1_2)
,并定义 Migration
对象:
static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { database.execSQL("ALTER TABLE user ADD COLUMN age INTEGER"); } };
问题2:如何在 Room 中执行多表关联查询?
解答:
- 在 DAO 中使用
@Transaction
注解保证事务一致性。 - 定义嵌套对象或自定义返回类型:
@Transaction @Query("SELECT FROM user JOIN address ON user.id = address.userId WHERE user.id = :userId") List<UserWithAddress> getUserWithAddress(int userId);