Room
是一种ORM(对象关系映射)框架,可以用OOP(面向对象)的思路开发数据库,有点像早期的greenDAO,不过Room
作为Jetpack
的一员,能够返回更多类型的数据,比如能直接返回DataSource.Factory
来友好的支持Paging
的使用,本文主要总结基础的使用和原理。
Jetpack笔记代码
本文源码基于SDK 29
引入依赖:
def room_version = "2.2.3"
implementation "androidx.room:room-runtime:$room_version"
//注解处理器,用于编译期根据注解来生成类
annotationProcessor "androidx.room:room-compiler:$room_version"
用@Entity
表示一个实体,即数据库中表的定义,
//声明一个实体User,表名为t_user
@Entity(tableName = "t_user")
class User {
@PrimaryKey(autoGenerate = true) //int型的自增主键
@ColumnInfo(name = "id") //表中字段的名字,不填则使用成员变量名
private int mId;
@Ignore //Ignore注解表示不进行数据库映射,只存在于内存中
private boolean mSelected;
}
使用@Dao
声明数据访问对象,即表的操作,
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) //新增数据,发生冲突则替换
void insertUsers(User... users);
@Update(onConflict = OnConflictStrategy.REPLACE) //更新数据,发生冲突则替换
int updateUsers(User... users);
@Delete
void deleteUsers(User... users); //删除数据
@Query("SELECT * FROM t_user") //查询数据
List<User> queryUsers();
}
定义完表,还需要用@Database
定义数据库,
//entities表示这个数据库都有哪些表,version表示数据库版本,用于数据库升级
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
//提供dao对象给业务层使用
public abstract UserDao userDao();
}
来到activity,进行使用
RoomActivity extends AppCompatActivity {
void onCreate(Bundle savedInstanceState) {
//创建数据库对象
mAppDatabase = Room.databaseBuilder(this, AppDatabase.class, AppDatabase.DB_NAME)
.allowMainThreadQueries() //允许主线程操作数据库,不推荐
.build();
//获取dao对象
mUserDao = mAppDatabase.userDao();
//操作数据库
mUserDao.insertUsers(user);
}
}
首先看看数据库的创建,进入AppDatabase
类,点击查看他的实现类AppDatabase_Impl
,
//AppDatabase_Impl.java
SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
void createAllTables(SupportSQLiteDatabase _db) {
//创建表
_db.execSQL("CREATE TABLE IF NOT EXISTS `t_user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT)");
}
};
}
@Override
public UserDao userDao() {
if (_userDao != null) {
return _userDao;
} else {
synchronized(this) {
if(_userDao == null) {
//创建dao对象
_userDao = new UserDao_Impl(this);
}
return _userDao;
}
}
}
来到UserDao_Impl
,
//UserDao_Impl.java
UserDao_Impl(RoomDatabase __db) {
this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) {
@Override
public String createQuery() {
//创建sql语句
return "INSERT OR REPLACE INTO `t_user` (`id`,`name`) VALUES (nullif(?, 0),?)";
}
@Override
public void bind(SupportSQLiteStatement stmt, User value) {
//将参数绑定到sql语句的指定位置
stmt.bindLong(1, value.getId());
if (value.getName() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getName());
}
}
};
}
@Override
public void insertUsers(final User... users) {
__insertionAdapterOfUser.insert(users);
}
insert会来到EntityInsertionAdapter
,
//EntityInsertionAdapter.java
void insert(T[] entities) {
final SupportSQLiteStatement stmt = acquire();
try {
for (T entity : entities) {
//根据前边实现的bind方法,绑定参数
bind(stmt, entity);
//执行stmt完成数据库操作
stmt.executeInsert();
}
} finally {
release(stmt);
}
}
//省略调用链:acquire - getStmt - createNewStatement
SupportSQLiteStatement createNewStatement() {
//获取前边创建的sql语句
String query = createQuery();
//最终去到SQLiteDatabase.compileStatement()里创建SQLiteStatement
return mDatabase.compileStatement(query);
}
Paging
(后续介绍)性能方面的问题暂不做分析。