# Room数据库

## 目录
- [Room架构](#room架构)
- [Entity定义](#entity定义)
- [DAO接口](#dao接口)
- [Database配置](#database配置)
- [Room迁移](#room迁移)
- [Room与LiveData](#room与livedata)
- [Room最佳实践](#room最佳实践)
- [面试常见问题](#面试常见问题)

---

## Room架构

### Room 组件

```
┌─────────────┐
│  Entity     │  ←─── 数据模型
└──────┬──────┘
       │
┌──────▼──────┐
│    DAO      │  ←─── 数据访问接口
└──────┬──────┘
       │
┌──────▼──────┐
│  Database   │  ←─── 数据库配置
└─────────────┘
```

### Room 优势

1. **编译时检查**：SQL 语句编译时检查
2. **类型安全**：类型安全的数据访问
3. **支持 LiveData**：自动更新 UI
4. **支持 RxJava**：响应式编程
5. **简化代码**：减少样板代码

---

## Entity定义

### Entity 注解

```java
// 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 注解选项

```java
@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 定义

```java
// 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);
}
```

### 复杂查询

```java
@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 定义

```java
// 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 配置选项

```java
Room.databaseBuilder(context, AppDatabase.class, "database_name")
    .allowMainThreadQueries() // 允许主线程查询（不推荐）
    .fallbackToDestructiveMigration() // 破坏性迁移
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3) // 迁移
    .build();
```

---

## Room迁移

### 数据库迁移

```java
// 版本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 集成

```java
// 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 集成

```java
// 添加依赖
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. 使用单例模式

```java
// 数据库使用单例
public static synchronized AppDatabase getInstance(Context context) {
    if (instance == null) {
        instance = Room.databaseBuilder(...).build();
    }
    return instance;
}
```

### 2. 在后台线程操作

```java
// ✅ 正确：在后台线程操作
new Thread(() -> {
    userDao.insertUser(user);
}).start();

// ❌ 错误：在主线程操作（除非使用 allowMainThreadQueries）
userDao.insertUser(user);
```

### 3. 使用事务

```java
@Dao
public interface UserDao {
    @Transaction
    @Query("SELECT * FROM user")
    List<User> getAllUsers();
}
```

---

## 面试常见问题

### Q1: Room 的优势？

**答案：**
1. 编译时检查 SQL
2. 类型安全
3. 支持 LiveData
4. 支持 RxJava
5. 简化代码

### Q2: Room 的组件？

**答案：**
1. **Entity**：数据模型
2. **DAO**：数据访问接口
3. **Database**：数据库配置

### Q3: Room 迁移？

**答案：**
- 使用 Migration 类处理数据库升级
- 定义迁移规则
- 在 Database 配置中添加迁移

### Q4: Room 和 SQLite 的区别？

**答案：**
- **Room**：SQLite 的封装，提供类型安全、编译时检查
- **SQLite**：底层数据库，需要手动编写 SQL

---

*最后更新：2024年*
