
Room 是 Google 推出的 Android 官方持久化库,它在 SQLite 的基础上提供了一个抽象层,极大地简化了数据库操作。它通过编译时的 SQL 验证和注解,让开发者能够更安全、更高效地使用 SQLite。
对比维度 | Room | GreenDao |
|---|---|---|
开发公司 | Google官方(Jetpack架构组件) | GreenRobot(第三方开源库) |
支持平台 | Android,深度集成LiveData/ViewModel | Android,轻量级ORM,兼容性广 |
数据库类型 | SQLite抽象层,类型安全,编译时SQL验证 | 基于SQLite,代码生成策略,性能优化 |
API设计 | 注解驱动(@Entity/@Dao),支持RxJava/Flow | 代码生成模式,自动生成DAO类,API简洁 |
性能表现 | 插入1441ms/查询411ms(华为Mate10测试) | 插入2771ms/查询750ms(同条件测试),批量操作更快 |
缓存机制 | LiveData/Flowable自动缓存,实时UI更新 | 内存高效映射,支持异步操作 |
数据类型支持 | 强类型安全,支持自定义类型转换器 | 基本类型支持,需手动处理复杂类型 |
事务支持 | 编译时事务验证,集成Jetpack架构 | 基础事务支持,需手动管理 |
社区与文档 | 官方文档完善,更新频繁,生态成熟 | 社区活跃,但更新较慢,文档分散 |
代码生成 | 运行时通过注解处理器生成DAO实现 | 编译时生成DAO类,减少样板代码 |
加密支持 | 需自定义实现或第三方库 | 原生支持数据库加密 |
学习曲线 | 需掌握Jetpack架构,注解配置较复杂 | 简单易用,快速上手,配置灵活 |
典型场景 | MVVM架构项目,需要实时数据同步 | 高性能需求场景,批量数据操作 |
Room 有三个主要组件:
代表数据库中的一张表。 使用 @Entity 注解标记一个数据类。 类中的每个属性(字段)默认对应表中的一列。
@Entity(tableName = "users") // 指定表名
data class User(
@PrimaryKey val uid: Int, // 主键
@ColumnInfo(name = "first_name") val firstName: String?, // 指定列名
@ColumnInfo(name = "last_name") val lastName: String?
)包含用于访问数据库的方法(增删改查)。 使用 @Dao 注解标记一个接口或抽象类。 DAO 是 Room 的核心,所有数据库操作都通过 DAO 完成。
@Dao
interface UserDao {
@Query("SELECT * FROM users")
fun getAll(): List<User>
@Query("SELECT * FROM users WHERE uid IN (:userIds)")
fun loadAllByIds(userIds: IntArray): List<User>
@Query("SELECT * FROM users WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
fun findByName(first: String, last: String): User
@Insert
fun insertAll(vararg users: User)
@Update
fun update(user: User)
@Delete
fun delete(user: User)
}作为持久化数据的底层连接的主要访问点。 必须是一个抽象类,并继承自 RoomDatabase。 在注解中指定 entities(实体类)和 version(数据库版本)。
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao // 获取 DAO 实例
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database" // 数据库文件名
).build()
INSTANCE = instance
instance
}
}
}
}在 app/build.gradle 文件中添加:
dependencies {
def room_version = "2.6.1" // 请使用最新稳定版本
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// 如果使用 Kotlin 协程,还需要
implementation "androidx.room:room-ktx:$room_version"
// 如果使用 Kotlin,使用 kapt
kapt "androidx.room:room-compiler:$room_version"
}深色版本
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) // 自增主键
val id: Long,
val name: String,
val email: String
)@Dao
interface UserDao {
@Query("SELECT * FROM users")
suspend fun getAllUsers(): List<User> // 使用 suspend 支持协程
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Long): User?
@Insert
suspend fun insertUser(user: User): Long // 返回新插入行的主键
@Update
suspend fun updateUser(user: User)
@Delete
suspend fun deleteUser(user: User)
}@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"user_database"
)
// .addCallback(sRoomDatabaseCallback) // 可选:数据库创建/打开回调
.build()
INSTANCE = instance
instance
}
}
}
}深色版本
class MainActivity : AppCompatActivity() {
private lateinit var userDao: UserDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val db = AppDatabase.getInstance(this)
userDao = db.userDao()
// 在协程中执行数据库操作
lifecycleScope.launch {
// 插入
val userId = userDao.insertUser(User(0, "Alice", "alice@example.com"))
Log.d("DB", "Inserted user with id: $userId")
// 查询
val users = userDao.getAllUsers()
Log.d("DB", "All users: $users")
}
}
}@Query("SELECT * FROM users WHERE name LIKE :nameQuery ORDER BY name LIMIT :limit OFFSET :offset")
suspend fun searchUsers(nameQuery: String, limit: Int, offset: Int): List<User>
@Query("SELECT COUNT(*) FROM users")
suspend fun getUserCount(): Int查询结果可以映射到非实体类的数据类。
data class UserNameAndEmail(
val name: String,
val email: String
)
@Dao
interface UserDao {
@Query("SELECT name, email FROM users")
suspend fun loadUserNamesAndEmails(): List<UserNameAndEmail>
}Room 支持一对一、一对多、多对多关系,但需要手动处理。
例如 User 有多个 Pet。
深色版本
@Entity
data class Pet(
@PrimaryKey val petId: Long,
val name: String,
val userId: Long // 外键,关联 User.id
)
data class UserWithPets(
@Embedded val user: User,
@Relation(
parentColumn = "id",
entityColumn = "userId"
)
val pets: List<Pet>
)
@Dao
interface UserDao {
@Transaction
@Query("SELECT * FROM User")
suspend fun getUsersWithPets(): List<UserWithPets>
}需要一个中间表(Junction Table)。
@Entity(primaryKeys = ["userId", "bookId"])
data class UserBookCrossRef(
val userId: Long,
val bookId: Long
)
@Entity
data class Book(
@PrimaryKey val bookId: Long,
val title: String
)
data class UserWithBooks(
@Embedded val user: User,
@Relation(
entity = Book::class,
parentColumn = "id",
entityColumn = "bookId",
associateBy = Junction(UserBookCrossRef::class)
)
val books: List<Book>
)返回 LiveData:数据变化时自动通知观察者。
@Query("SELECT * FROM users ORDER BY name")
fun loadUsers(): LiveData<List<User>> // 不再是 suspend返回 Flow:更强大的响应式流,支持协程。
@Query("SELECT * FROM users ORDER BY name")
fun getUsersFlow(): Flow<List<User>>在协程作用域中收集:
lifecycleScope.launch {
userDao.getUsersFlow().collect { users ->
// 更新 UI
}
}当数据库结构变化(如添加列、修改表)时,需要升级版本并提供迁移策略。
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE users ADD COLUMN last_updated INTEGER NOT NULL DEFAULT 0")
}
}
// 在构建数据库时添加
Room.databaseBuilder(context, AppDatabase::class.java, "database")
.addMigrations(MIGRATION_1_2)
.build()private val sRoomDatabaseCallback = object : RoomDatabase.Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
// 数据库打开时执行
}
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
// 数据库创建时执行,可预填充数据
}
}将复杂对象(如 Date, List, 自定义对象)存储为数据库支持的类型(如 Long, String)。
深色版本
class Converters {
@TypeConverter
fun fromTimestamp(value: Long?): Date? {
return value?.let { Date(it) }
}
@TypeConverter
fun dateToTimestamp(date: Date?): Long? {
return date?.time
}
}
// 在数据库类中注册
@Database(entities = [User::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
// ...
}Room 通过注解和编译时代码生成,极大地简化了 Android 上的 SQLite 操作。从定义实体、DAO 到构建数据库,整个过程清晰、类型安全。结合协程、LiveData 和 Flow,可以构建出响应迅速、用户体验良好的应用。
精通 Room 的关键在于: