Room 数据存储

发布于:2025-08-15 ⋅ 阅读:(9) ⋅ 点赞:(0)

Room 是 Android Jetpack 组件中的一个持久化库,它是在 SQLite 上提供了一个抽象层,使得数据库访问更加简单、高效。

核心组件

Room 主要由三个组件组成:

  1. Entity(实体):表示数据库中的表

  2. DAO(Data Access Object):包含用于访问数据库的方法

  3. 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

  1. 添加依赖

implementation "androidx.room:room-runtime:2.4.0"
kapt "androidx.room:room-compiler:2.4.0"
implementation "androidx.room:room-ktx:2.4.0"
  1. 创建实体、DAO 和数据库类(如上所示)

  2. 在应用中使用

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 的高级特性

  1. 关系:使用 @Relation@ForeignKey 定义表间关系

  2. 类型转换器:使用 @TypeConverter 存储自定义类型

  3. 数据库迁移:使用 Migration 类处理数据库版本升级

  4. 预填充数据库:从 assets 或文件预加载数据

  5. 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();

五、最佳实践

  1. 不要在主线程操作数据库:Room 默认不允许在主线程访问数据库

  2. 合理使用 LiveData/RxJava:简化异步操作

  3. 适当使用事务:对多个相关操作使用 @Transaction

  4. 合理设计数据库版本迁移策略:避免数据丢失

  5. 考虑使用 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);


网站公告

今日签到

点亮在社区的每一天
去签到