Room 数据存储
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 {@Insertsuspend fun insert(user: User)@Updatesuspend fun update(user: User)@Deletesuspend 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(): UserDaocompanion object {private var INSTANCE: AppDatabase? = nullfun getDatabase(context: Context): AppDatabase {return INSTANCE ?: synchronized(this) {val instance = Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"app_database").build()INSTANCE = instanceinstance}}}
}
使用 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;@Ignoreprivate 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 {@Insertvoid insert(User user);@Insertvoid insertAll(User... users);@Updatevoid update(User user);@Deletevoid 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>() {@Overrideprotected 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 -> {// 更新UIadapter.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) {@Overridepublic 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 {@TypeConverterpublic static Date fromTimestamp(Long value) {return value == null ? null : new Date(value);}@TypeConverterpublic 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 {@Embeddedpublic 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 -> {// 更新RecyclerViewadapter.submitList(users);
});// 插入新用户
User newUser = new User("赵六", 28);
viewModel.insert(newUser);