字段名 | 数据类型 | 约束条件 | 说明 |
---|---|---|---|
user_id | INTEGER | PRIMARY KEY AUTOINCREMENT | 唯一用户标识 |
username | TEXT | UNIQUE NOT NULL | 用户名(建议长度限制) |
TEXT | UNIQUE NOT NULL | 邮箱地址 | |
password_hash | TEXT | NOT NULL | 密码哈希值(加盐存储) |
created_at | INTEGER | DEFAULT (datetime(‘now’,’localtime’)) | 注册时间戳 |
updated_at | INTEGER | DEFAULT (datetime(‘now’,’localtime’)) | 最后更新时间戳 |
avatar_url | TEXT | NULLABLE | 头像图片URL |
device_id | TEXT | NULLABLE | 设备唯一标识(可选) |
敏感字段 | 加密方式 | 实现方案 |
---|---|---|
password_hash | SHA-256 + 随机盐值 | Android Keystore存储密钥 |
token | AES对称加密 | EncryptedSharedPreferences |
private_key | RSA非对称加密 | KeyStore.PrivateKeyEntry |
// User.kt实体类 @Entity(tableName = "users") data class User( @PrimaryKey(autoGenerate = true) val userId: Int = 0, @ColumnInfo(name = "username") val username: String, @ColumnInfo(name = "email") val email: String, @ColumnInfo(name = "password_hash") val passwordHash: String, @ColumnInfo(name = "created_at") val createdAt: Long = System.currentTimeMillis() ) // UserDao.kt接口 @Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.ABORT) suspend fun insertUser(user: User) @Query("SELECT FROM users WHERE email = :email LIMIT 1") fun getUserByEmail(email: String): Flow<User?> @Update suspend fun updateUser(user: User) }
操作类型 | 推荐实现方式 | 注意事项 |
---|---|---|
插入操作 | suspend函数 + OnConflictStrategy | 处理主键冲突策略 |
查询操作 | LiveData/Flow | 避免内存泄漏 |
更新操作 | 带版本号的更新 | 确保并发修改一致性 |
删除操作 | 参数校验后执行 | 防止误删重要数据 |
索引优化:
email
、username
字段创建唯一索引created_at
字段创建普通索引用于排序查询分页查询:
@Query("SELECT FROM users ORDER BY created_at DESC LIMIT :limit OFFSET :offset") fun getUsersPaginated(limit: Int, offset: Int): DataSource.Factory<Int, User>
批量操作:
insertUserList
代替循环插入场景 | 解决方案 |
---|---|
全盘加密 | 启用SQLite的WAL模式配合Android Keystore生成加密密钥 |
字段级加密 | 使用AES/GCM模式加密敏感字段,密钥存储在Keystore |
文件存储加密 | SQLite数据库文件存放在应用专属目录,配合SELinux策略限制访问权限 |
版本号 | 迁移方案 | |
---|---|---|
2 | 新增手机号字段 | 创建临时表→数据复制→重命名表→删除旧表 |
3 | 密码加密算法升级 | 添加新字段存储bcrypt哈希→更新现有用户数据→修改DAO接口 |
4 | 拆分大字段到独立表 | 创建新表→建立外键关联→迁移数据→修改原表结构 |
A:可通过以下两种方式实现:
account_id
字段,每个账户对应独立IDA:建议采用以下架构: