上一篇
安卓开发之数据库设计
- 行业动态
- 2025-04-22
- 4
安卓数据库选型
数据库类型 | 特点 | 适用场景 |
---|---|---|
SQLite | 轻量级嵌入式数据库,支持SQL语法,无需独立服务器 | 本地数据存储(如用户配置、缓存) |
Room | 基于SQLite的抽象层,提供编译时校验,支持LiveData | 需要与架构组件(如ViewModel)联动的复杂业务 |
Realm | 面向对象的数据库,高性能,跨平台支持 | 频繁读写的实时数据(如IoT应用) |
数据库设计核心原则
数据规范化
- 遵循三范式:消除重复字段、确保依赖关系合理
- 示例:用户表(user_id, username) 与订单表(order_id, user_id) 通过外键关联
字段类型优化
| 数据类型 | 适用场景 | 安卓对应类型 |
|———|———-|————–|
| TEXT | 字符串(如用户名) | String |
| INTEGER | 整数(如年龄) | Int |
| REAL | 浮点数(如经纬度) | Double |
| BLOB | 二进制数据(如图片)| byte[] |主键策略
- 自增主键:适用于需要唯一标识的场景(如订单号)
- UUID主键:分布式系统中防止冲突(如多设备同步)
Room数据库实战设计
// 1. 定义实体类 @Entity(tableName = "users") data class User( @PrimaryKey(autoGenerate = true) val id: Int, @ColumnInfo(name = "username") val name: String, @ColumnInfo(name = "create_time") val createTime: Long ) // 2. 创建DAO接口 @Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUser(user: User) @Query("SELECT FROM users WHERE id = :userId") fun getUserById(userId: Int): LiveData<User> } // 3. 构建数据库 @Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
数据库操作关键API
操作类型 | Room API | 说明 |
---|---|---|
插入数据 | insert() | 支持冲突策略(REPLACE/ABORT) |
更新数据 | update() | 需配合@Query使用 |
删除数据 | delete() | 支持条件删除 |
查询数据 | @Query | 支持返回LiveData/Flow |
常见问题解决方案
数据库版本升级
// 1. 修改@Database注解的version属性 @Database(version = 2) // 从1升级到2 // 2. 实现Migration接口 val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER") } } // 3. 构建数据库时传入迁移对象 Room.databaseBuilder(context, AppDatabase::class.java, "app.db") .addMigrations(MIGRATION_1_2) .build()
大数据量分页查询
@Dao interface LargeDataDao { @Query("SELECT FROM data_table LIMIT :limit OFFSET :offset") fun getPagedData(limit: Int, offset: Int): List<Data> }
性能优化技巧
索引优化
- 对高频查询字段建立索引(如
CREATE INDEX idx_username ON users(username)
) - 注意过多索引会影响写入性能
- 对高频查询字段建立索引(如
事务处理
@Transaction suspend fun updateUsers(users: List<User>) { userDao.deleteAll() userDao.insertUsers(users) }
内存缓存结合
- 使用
@Query("SELECT FROM users")
配合LiveData
实现自动更新 - 重要数据可额外使用
SharedPreferences
缓存
- 使用
【相关问题解答】
Q1:SQLite和Room应该如何选择?
答:SQLite适合简单场景(如仅需CRUD操作),可直接使用SQLiteOpenHelper
,Room更适合复杂业务场景,其优势包括:
- 编译时校验SQL语句正确性
- 自动生成DAO接口实现
- 内置支持LiveData/Flow响应式编程
- 提供迁移工具和类型安全机制
Q2:如何处理一对一/一对多的表关系?
答:
一对一关系:合并表结构或使用
FOREIGN KEY
约束-用户表与详情表一对一 CREATE TABLE user_details ( id INTEGER PRIMARY KEY, user_id INTEGER, bio TEXT, FOREIGN KEY(user_id) REFERENCES users(id) )
一对多关系:在”多”方表中添加外键字段
// Order表(多方)包含user_id外键 @Entity data class Order( @PrimaryKey val orderId: Int, val userId: Int, // 关联用户表的主键 val amount: Double )