Room数据库定义规范
实体类定义
@Entity(tableName = "user") public class User { @PrimaryKey(autoGenerate = true) public int id; @ColumnInfo(name = "username") public String userName; @ColumnInfo(name = "age") private int age; // 必须提供无参构造函数 public User(String userName, int age) { this.userName = userName; this.age = age; } }
DAO接口定义
@Dao public interface UserDao { @Query("SELECT FROM user WHERE id = :userId") User getUserById(int userId); @Insert(onConflict = OnConflictStrategy.REPLACE) long insertUser(User user); @Update int updateUser(User user); @Delete int deleteUser(User user); // 自定义复杂查询 @Query("SELECT COUNT() FROM user WHERE age > :minAge") int countUsersOlderThan(int minAge); }
数据库类定义
@Database(entities = {User.class}, version = 2) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); // 数据库迁移策略 static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { // 创建新表 database.execSQL("CREATE TABLE IF NOT EXISTS user_backup (id INTEGER PRIMARY KEY, username TEXT)"); // 数据迁移 database.execSQL("INSERT INTO user_backup(id,username) SELECT id,username FROM user"); // 删除旧表 database.execSQL("DROP TABLE user"); // 重命名新表 database.execSQL("ALTER TABLE user_backup RENAME TO user"); } }; }
数据库初始化与使用
AppDatabase db = Room.databaseBuilder( context, AppDatabase.class, "app-database" ) .addMigrations(MIGRATION_1_2) // 添加迁移策略 .allowMainThreadQueries() // 开发阶段允许主线程操作(生产环境需移除) .build(); // 数据操作示例 UserDao userDao = db.userDao(); User user = new User("John", 25); userDao.insertUser(user);
常见问题与解决方案
问题现象 | 解决方案 |
---|---|
数据库版本升级导致崩溃 | 实现Migration接口处理数据迁移 |
主线程操作数据库异常 | 使用Executors或异步任务处理 |
编译时报错:缺少xxx表 | 检查@Entity注解和数据库版本号 |
数据插入失败 | 检查@PrimaryKey冲突策略和字段约束 |
相关问题解答
Q1:Room相比直接使用SQLite有哪些优势?
- 编译时校验:通过注解生成代码,提前发现语法错误
- 对象关系映射:自动处理Java对象与数据库表的转换
- 活跃对象支持:@LiveData注解实现数据观察
- 类型安全:避免运行时SQL拼接错误
- 更好的架构支持:与ViewModel、Coroutines无缝配合
Q2:如何处理多表关联查询?
@Transaction @Query("SELECT FROM user WHERE id IN (SELECT user_id FROM order)") List<User> getUsersWithOrders();
通过@Transaction
保证原子性,使用标准SQL进行多表JOIN操作,对于复杂查询,建议将业务逻辑下沉到Repository层