7.3 KiB
7.3 KiB
Room数据库
目录
Room架构
Room 组件
┌─────────────┐
│ Entity │ ←─── 数据模型
└──────┬──────┘
│
┌──────▼──────┐
│ DAO │ ←─── 数据访问接口
└──────┬──────┘
│
┌──────▼──────┐
│ Database │ ←─── 数据库配置
└─────────────┘
Room 优势
- 编译时检查:SQL 语句编译时检查
- 类型安全:类型安全的数据访问
- 支持 LiveData:自动更新 UI
- 支持 RxJava:响应式编程
- 简化代码:减少样板代码
Entity定义
Entity 注解
// Entity:数据模型
@Entity(tableName = "user")
public class User {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "user_name")
private String name;
private String email;
private int age;
// Getters and Setters
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 String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
Entity 注解选项
@Entity(
tableName = "user",
indices = {@Index("name"), @Index(value = {"name", "age"})},
foreignKeys = {
@ForeignKey(
entity = Department.class,
parentColumns = "id",
childColumns = "department_id"
)
}
)
public class User {
@PrimaryKey
private int id;
@ColumnInfo(name = "department_id")
private int departmentId;
}
DAO接口
DAO 定义
// DAO:数据访问对象
@Dao
public interface UserDao {
// 查询
@Query("SELECT * FROM user")
List<User> getAllUsers();
@Query("SELECT * FROM user WHERE id = :id")
User getUserById(int id);
@Query("SELECT * FROM user WHERE age > :age")
List<User> getUsersByAge(int age);
// 插入
@Insert
void insertUser(User user);
@Insert
void insertUsers(User... users);
// 更新
@Update
void updateUser(User user);
// 删除
@Delete
void deleteUser(User user);
@Query("DELETE FROM user WHERE id = :id")
void deleteUserById(int id);
}
复杂查询
@Dao
public interface UserDao {
// 多表查询
@Query("SELECT * FROM user u INNER JOIN department d ON u.department_id = d.id")
List<UserWithDepartment> getUsersWithDepartment();
// 参数查询
@Query("SELECT * FROM user WHERE name LIKE :name AND age > :age")
List<User> searchUsers(String name, int age);
// 返回 LiveData
@Query("SELECT * FROM user")
LiveData<List<User>> getAllUsersLive();
// 返回 Flowable(RxJava)
@Query("SELECT * FROM user")
Flowable<List<User>> getAllUsersFlowable();
}
Database配置
Database 定义
// Database:数据库配置
@Database(
entities = {User.class, Department.class},
version = 1,
exportSchema = false
)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
public abstract DepartmentDao departmentDao();
private static AppDatabase instance;
public static synchronized AppDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(
context.getApplicationContext(),
AppDatabase.class,
"app_database"
).build();
}
return instance;
}
}
Database 配置选项
Room.databaseBuilder(context, AppDatabase.class, "database_name")
.allowMainThreadQueries() // 允许主线程查询(不推荐)
.fallbackToDestructiveMigration() // 破坏性迁移
.addMigrations(MIGRATION_1_2, MIGRATION_2_3) // 迁移
.build();
Room迁移
数据库迁移
// 版本1 → 版本2
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE user ADD COLUMN phone TEXT");
}
};
// 版本2 → 版本3
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE address (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"user_id INTEGER," +
"address TEXT" +
")");
}
};
// 配置迁移
Room.databaseBuilder(context, AppDatabase.class, "database_name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
.build();
Room与LiveData
LiveData 集成
// DAO 返回 LiveData
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
LiveData<List<User>> getAllUsers();
@Query("SELECT * FROM user WHERE id = :id")
LiveData<User> getUserById(int id);
}
// 观察数据变化
userDao.getAllUsers().observe(this, users -> {
adapter.updateUsers(users);
});
RxJava 集成
// 添加依赖
dependencies {
implementation 'androidx.room:room-rxjava2:2.3.0'
}
// DAO 返回 Flowable
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
Flowable<List<User>> getAllUsers();
}
// 使用
userDao.getAllUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(users -> {
adapter.updateUsers(users);
});
Room最佳实践
1. 使用单例模式
// 数据库使用单例
public static synchronized AppDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(...).build();
}
return instance;
}
2. 在后台线程操作
// ✅ 正确:在后台线程操作
new Thread(() -> {
userDao.insertUser(user);
}).start();
// ❌ 错误:在主线程操作(除非使用 allowMainThreadQueries)
userDao.insertUser(user);
3. 使用事务
@Dao
public interface UserDao {
@Transaction
@Query("SELECT * FROM user")
List<User> getAllUsers();
}
面试常见问题
Q1: Room 的优势?
答案:
- 编译时检查 SQL
- 类型安全
- 支持 LiveData
- 支持 RxJava
- 简化代码
Q2: Room 的组件?
答案:
- Entity:数据模型
- DAO:数据访问接口
- Database:数据库配置
Q3: Room 迁移?
答案:
- 使用 Migration 类处理数据库升级
- 定义迁移规则
- 在 Database 配置中添加迁移
Q4: Room 和 SQLite 的区别?
答案:
- Room:SQLite 的封装,提供类型安全、编译时检查
- SQLite:底层数据库,需要手动编写 SQL
最后更新:2024年