Room 是 Android Jetpack 组件中的一个持久化库,它是在 SQLite 上提供了一个抽象层,使得数据库访问更加简单、高效。
核心组件
Room 主要由三个组件组成:
Entity(实体):表示数据库中的表
DAO(Data Access Object):包含用于访问数据库的方法
Database(数据库):持有数据库并作为应用持久化数据的主要访问点
1. Entity(实体)
Entity 是一个数据类,用于定义数据库中的表结构。
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "first_name") val firstName: String,
@ColumnInfo(name = "last_name") val lastName: String,
val age: Int
)
常用注解:
@Entity
:标记类为 Room 实体@PrimaryKey
:定义主键@ColumnInfo
:自定义列名@Ignore
:忽略字段,不存入数据库
2. DAO(数据访问对象)
DAO 是一个接口,定义了访问数据库的方法。
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Update
suspend fun update(user: User)
@Delete
suspend fun delete(user: User)
@Query("SELECT * FROM users")
fun getAllUsers(): LiveData<List<User>>
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
}
常用注解:
@Insert
、@Update
、@Delete
:基本 CRUD 操作@Query
:自定义 SQL 查询
3. Database(数据库)
Database 是一个抽象类,扩展自 RoomDatabase。
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
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
}
}
}
}
使用 Room
添加依赖:
implementation "androidx.room:room-runtime:2.4.0"
kapt "androidx.room:room-compiler:2.4.0"
implementation "androidx.room:room-ktx:2.4.0"
创建实体、DAO 和数据库类(如上所示)
在应用中使用:
val db = AppDatabase.getDatabase(applicationContext)
val userDao = db.userDao()
// 插入用户
lifecycleScope.launch {
userDao.insert(User(0, "John", "Doe", 30))
}
// 观察用户列表
userDao.getAllUsers().observe(this) { users ->
// 更新 UI
}
Room 的高级特性
关系:使用
@Relation
、@ForeignKey
定义表间关系类型转换器:使用
@TypeConverter
存储自定义类型数据库迁移:使用
Migration
类处理数据库版本升级预填充数据库:从 assets 或文件预加载数据
RxJava/Coroutines 支持:异步操作支持
Room 数据库(Java 版)
一、基本设置
1. 添加依赖
在 build.gradle
文件中添加:
dependencies {
def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// 可选 - Kotlin扩展和协程支持
implementation "androidx.room:room-ktx:$room_version"
// 可选 - RxJava支持
implementation "androidx.room:room-rxjava2:$room_version"
}
二、核心组件(Java实现)
1. Entity(实体类)
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "user_name")
private String name;
@ColumnInfo(name = "user_age")
private int age;
@Ignore
private String tempData; // 不会被存储到数据库
// 构造方法
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getter 和 Setter 方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
2. DAO(数据访问对象)
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Insert
void insertAll(User... users);
@Update
void update(User user);
@Delete
void delete(User user);
@Query("DELETE FROM users")
void deleteAll();
@Query("SELECT * FROM users")
List<User> getAll();
@Query("SELECT * FROM users WHERE id = :userId")
User getUserById(int userId);
@Query("SELECT * FROM users WHERE user_name LIKE :name LIMIT 1")
User findUserByName(String name);
// 使用LiveData观察数据变化
@Query("SELECT * FROM users")
LiveData<List<User>> getAllLiveUsers();
}
3. Database(数据库类)
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.getApplicationContext(),
AppDatabase.class,
"app_database")
.fallbackToDestructiveMigration() // 数据库升级时清空数据
.build();
}
}
}
return INSTANCE;
}
}
三、数据库操作
1. 初始化数据库
AppDatabase db = AppDatabase.getDatabase(getApplicationContext());
UserDao userDao = db.userDao();
2. 插入数据
// 在主线程执行会抛出异常,必须在后台线程执行
new Thread(() -> {
User user = new User("张三", 25);
userDao.insert(user);
}).start();
// 或者使用AsyncTask
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
User user = new User("李四", 30);
userDao.insert(user);
return null;
}
}.execute();
3. 查询数据
// 同步查询(需在后台线程)
List<User> users = userDao.getAll();
// 异步查询(使用LiveData观察)
userDao.getAllLiveUsers().observe(this, users -> {
// 更新UI
adapter.setUsers(users);
});
4. 更新和删除
new Thread(() -> {
// 更新
User user = userDao.getUserById(1);
if (user != null) {
user.setName("王五");
userDao.update(user);
}
// 删除
userDao.delete(user);
}).start();
四、高级功能
1. 数据库迁移
// 定义迁移策略
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE users ADD COLUMN email TEXT");
}
};
// 应用迁移
Room.databaseBuilder(context, AppDatabase.class, "app_database")
.addMigrations(MIGRATION_1_2)
.build();
2. 类型转换器
public class Converters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
// 在Database类中添加
@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
// ...
}
3. 关系查询
// 一对多关系
public class UserWithPets {
@Embedded
public User user;
@Relation(
parentColumn = "id",
entityColumn = "user_id"
)
public List<Pet> pets;
}
// 在DAO中
@Transaction
@Query("SELECT * FROM users")
public List<UserWithPets> getUsersWithPets();
五、最佳实践
不要在主线程操作数据库:Room 默认不允许在主线程访问数据库
合理使用 LiveData/RxJava:简化异步操作
适当使用事务:对多个相关操作使用
@Transaction
合理设计数据库版本迁移策略:避免数据丢失
考虑使用 Repository 模式:将数据库操作与 ViewModel 解耦
六、完整示例
// 在ViewModel中使用
public class UserViewModel extends AndroidViewModel {
private UserDao userDao;
private LiveData<List<User>> allUsers;
public UserViewModel(@NonNull Application application) {
super(application);
AppDatabase db = AppDatabase.getDatabase(application);
userDao = db.userDao();
allUsers = userDao.getAllLiveUsers();
}
public LiveData<List<User>> getAllUsers() {
return allUsers;
}
public void insert(User user) {
AppDatabase.databaseWriteExecutor.execute(() -> {
userDao.insert(user);
});
}
}
// 在Activity中使用
UserViewModel viewModel = new ViewModelProvider(this).get(UserViewModel.class);
viewModel.getAllUsers().observe(this, users -> {
// 更新RecyclerView
adapter.submitList(users);
});
// 插入新用户
User newUser = new User("赵六", 28);
viewModel.insert(newUser);