上一篇
安卓应用开发数据库设计
- 行业动态
- 2025-04-22
- 3
数据库选型分析
方案 | 适用场景 | 特点 |
---|---|---|
SQLite | 本地轻量级存储 | 文件型数据库,支持ACID,适合结构化数据,无需独立服务器 |
Room | 需要架构组件集成的SQLite | 提供抽象层,支持LiveData/Coroutines,编译时验证SQL正确性 |
Realm | 高性能对象存储 | 支持复杂查询,跨平台,但学习成本较高 |
Firebase Firestore | 实时同步的云端存储 | 自动离线缓存,全球部署,按使用量计费 |
SharedPreferences | 键值对存储 | 仅适合简单配置数据,无查询能力 |
表结构设计规范
示例:用户信息表(users)
| 字段名 | 数据类型 | 主键/索引 | 约束条件 | 说明 |
|————–|————-|———-|——————–|——————————-|
| uId | INTEGER | PRIMARY KEY AUTOINCREMENT | 自增主键 |
| username | TEXT | UNIQUE | NOT NULL | 30字符以内唯一用户名 |
| passwordHash | TEXT | | NOT NULL | SHA-256加密存储 |
| email | TEXT | UNIQUE | NOT NULL | 邮箱格式校验 |
| createTime | LONG | | NOT NULL | 时间戳(1970基准毫秒数) |
| lastLogin | LONG | | | 最近登录时间 |
| status | INTEGER | | DEFAULT 0 | 0:正常 1:封禁 |
索引优化策略
必要索引:
- 主键自动创建唯一索引
- 频繁查询的WHERE条件字段(如email/username)
- ORDER BY/GROUP BY涉及的字段
复合索引:
CREATE INDEX idx_user_status_time ON users(status, createTime);
避免过度索引:
- 每新增一个索引会降低写操作性能
- 优先为高频查询路径创建索引
数据库版本管理
版本号 | 升级操作 | 注意事项 |
---|---|---|
1 | 初始创建users表 | |
2 | 新增lastLogin字段 | ALTER TABLE操作需谨慎 |
3 | 修改passwordHash长度限制 | 需迁移现有数据 |
4 | 添加消息表并建立外键关联 | 先创建新表再处理关联数据 |
Room实战要点
实体类定义:
@Entity(tableName = "users", indices = {@Index(value = {"email"}, unique = true)}) public class User { @PrimaryKey(autoGenerate = true) public int uId; @ColumnInfo(name = "username", collation = ColumnInfo.COLLATION_NOCASE) public String username; // 其他字段及关系注解... }
DAO层方法:
@Dao public interface UserDao { @Query("SELECT FROM users WHERE status = :status ORDER BY lastLogin DESC") List<User> getActiveUsers(int status); @Insert(onConflict = OnConflictStrategy.REPLACE) long insertUser(User user); @Update void updateLoginTime(String email, long time); }
数据库构建器:
public class AppDatabase extends RoomDatabase { private static final String MIGRATION_FROM_2_TO_3 = "MIGRATION_2_3"; static { Room.migrationsEnabled(true); // Android P+ 必须显式开启 } private static volatile AppDatabase INSTANCE; public static AppDatabase getInstance(Context context) { if (INSTANCE == null) { synchronized (AppDatabase.class) { INSTANCE = Room.databaseBuilder(context, AppDatabase.class, "app.db") .addMigrations(new Migration_2_3()) .build(); } } return INSTANCE; } }
数据安全措施
静态加密:
// 在Room配置中启用加密 .openHelperFactory(factory) // factory实现AES加密逻辑
动态防护:
- 敏感字段前端模糊处理(如手机号显示)
- SQL注入防护:使用参数化查询代替字符串拼接
- 关键操作二次验证(如删除数据前弹窗确认)
常见问题与解决方案
Q1:数据库升级导致应用崩溃
- 原因:未处理版本迁移,新旧表结构不兼容
- 解决方案:
- 在
Room.databaseBuilder
中添加.fallbackToDestructiveMigration()
(慎用,会清空数据) - 编写Migration脚本:
static final Migration MIGRATION_3_4 = new Migration(3, 4) { @Override public void migrate(@NonNull SupportSQLiteDatabase db) { db.execSQL("ALTER TABLE users ADD COLUMN phone TEXT"); // 处理默认值和数据迁移逻辑 } };
- 在
Q2:多表关联查询性能低下
- 原因:缺乏有效索引或N+1查询问题
- 优化方案:
- 使用
@Transaction
注解批量查询关联数据 - 在DAO层预加载关联数据:
@Transaction @Query("SELECT FROM orders WHERE userId = :userId") List<Order> getOrdersWithUser(String userId);
- 使用