上一篇
安卓开发怎么查询数据库
- 行业动态
- 2025-04-22
- 8
Warning: mysqli_query(): MySQL server has gone away in /data/www/wwwroot/kdun.com/public/ask/wp-includes/class-wpdb.php on line 2344
Warning: mysqli_query(): Error reading result set's header in /data/www/wwwroot/kdun.com/public/ask/wp-includes/class-wpdb.php on line 2344
SQLite数据库查询
使用SQLiteDatabase
直接查询
- 核心类:
SQLiteDatabase
(通过SQLiteOpenHelper
管理) - 查询方法:
rawQuery(String sql, String[] selectionArgs)
:直接执行SQL语句。query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
:参数化查询。
- 示例代码:
// 获取可读数据库 SQLiteDatabase db = helper.getReadableDatabase(); // 查询users表中age大于?的记录 Cursor cursor = db.query("users", new String[]{"id", "name", "age"}, "age > ?", new String[]{"18"}, null, null, null); while (cursor.moveToNext()) { int id = cursor.getInt(0); String name = cursor.getString(1); int age = cursor.getInt(2); // 处理数据 } cursor.close(); // 必须关闭Cursor
使用ContentValues
批量插入后查询
- 适用场景:需要先插入数据再查询
- 示例代码:
// 插入数据 ContentValues values = new ContentValues(); values.put("name", "张三"); values.put("age", 25); db.insert("users", null, values);
// 查询所有用户
Cursor cursor = db.rawQuery(“SELECT FROM users”, null);
二、Room持久库查询
# 1. 定义实体和DAO
```java
// 实体类
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
public int id;
public String name;
public int age;
}
// DAO接口
@Dao
public interface UserDao {
@Query("SELECT FROM users WHERE age > :minAge")
List<User> getUsersByAge(int minAge);
}
使用@Query
实现复杂查询
功能 | 示例代码 |
---|---|
模糊查询 | @Query("SELECT FROM users WHERE name LIKE :name") List<User> search(String name) |
分页查询 | @Query("SELECT FROM users LIMIT :offset, :limit") List<User> paginate(int offset, int limit) |
关联查询(需@Transaction) | @Transaction @Query("SELECT FROM orders WHERE user_id = :userId") List<Order> getOrders(int userId) |
返回LiveData响应数据变化
@Dao public interface UserDao { @Query("SELECT FROM users WHERE age > :minAge") LiveData<List<User>> observeUsersByAge(int minAge); // 自动感知数据变更 }
网络数据库查询(以MySQL为例)
使用Retrofit+Gson组合
- 步骤:
- 定义API接口:
public interface ApiService { @GET("users") Call<List<User>> getUsers(@Query("age_gt") int age); }
- 发起请求并解析:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService api = retrofit.create(ApiService.class); Call<List<User>> call = api.getUsers(18); call.enqueue(new Callback<>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { List<User> users = response.body(); // 处理数据 } @Override public void onFailure(Call<List<User>> call, Throwable t) { // 处理错误 } });
- 定义API接口:
异步处理方案对比
方案 | 优点 | 缺点 |
---|---|---|
Retrofit+RxJava | 链式调用,灵活组合操作 | 学习成本较高 |
Retrofit+协程(Kotlin) | 简洁易读,避免回调地狱 | 仅支持Kotlin |
OkHttp+手动解析 | 完全控制请求过程 | 代码量大,易出错 |
注意事项
- 线程管理:
- 本地数据库操作应放在子线程(如
AsyncTask
、Executor
或协程) - Room支持在
LiveData
中自动异步查询
- 本地数据库操作应放在子线程(如
- 资源释放:
- SQLite的
Cursor
必须手动关闭 - Room的
Database
实例需正确管理生命周期
- SQLite的
- 安全性:
- 使用参数化查询防止SQL注入
- 敏感数据需加密存储(如使用
SQLCipher
)
相关问题与解答
Q1:Room和SQLite直接操作的主要区别是什么?
A:
| 对比维度 | SQLite直接操作 | Room持久库 |
|————–|———————————–|————————————|
| 开发效率 | 需手写大量SQL语句和CRUD逻辑 | 通过注解自动生成代码,减少模板代码 |
| 编译时检查 | 无类型安全检查 | 编译时验证SQL正确性,避免运行时错误 |
| 架构适配 | 需手动处理LiveData/ViewModel集成 | 内置支持LiveData和RxJava |
| 多表操作 | 需手动管理事务 | 支持@Transaction注解自动事务管理 |
Q2:如何在Room中实现多表联合查询?
A:
定义关联实体:
@Entity(tableName = "orders") public class Order { @PrimaryKey(autoGenerate = true) public int id; public int userId; public String product; }
在DAO中声明事务:
@Dao public interface OrderDao { @Transaction @Query("SELECT FROM users WHERE id IN (SELECT user_id FROM orders)") List<UserWithOrders> getUsersWithOrders(); // 需定义UserWithOrders为嵌套类 }
处理嵌套数据:
public class UserWithOrders { @Embedded public User user; @Relation(parentColumn = "id", entityColumn = "user_id") public List<Order> orders; }