使用Room查询时没有记录怎么办?
What happens if no records exists when I use Room to query?
我在我的 Android Studio 应用程序中使用 Room,当没有记录可供查询时,代码 A 会崩溃
使用Code B查询Room时没有记录怎么办?
@Dao
interface RecordDao {
// Code A
@Query("SELECT * FROM record_table where id=:id")
fun getByID(id:Int): Flow<RecordEntity>
// Code B
@Query("SELECT * FROM record_table")
fun getAll(): Flow<List<RecordEntity>>
}
如果您查看 room 为 RecordDao_Impl class RecordDao 实现生成的代码,您会注意到很多事情:
- 当 table 中不存在匹配记录时,getById 函数代码 return 为空,并且由于您的 'Code A' 函数 return 类型不为空,kotlin 抛出第一个函数的 NullPointerException。
- getAll 函数代码 return 是一个带有 ArrayList 的 Flow 对象,如果它找到任何记录,则会将它们添加到列表中,否则它只会将空的 ArrayList 发送到 Flow 对象,因此,您无论 room 是否找到匹配的记录,都会得到一个包含列表的流对象,因此不会抛出异常。
如果您在此处查看为这两个函数生成的代码,您可以更深入地理解这一点:
@Override
public Flow<RecordEntity> getByID(final int id) {
final String _sql = "SELECT * FROM record_table where id=?";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, id);
return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<RecordEntity>() {
@Override
public RecordEntity call() throws Exception {
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
final RecordEntity _result;
if (_cursor.moveToFirst()) {
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_result = new RecordEntity(_tmpId);
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}
@Override
public Flow<List<RecordEntity>> getAll() {
final String _sql = "SELECT * FROM record_table";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<List<RecordEntity>>() {
@Override
public List<RecordEntity> call() throws Exception {
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
final List<RecordEntity> _result = new ArrayList<RecordEntity>(_cursor.getCount());
while (_cursor.moveToNext()) {
final RecordEntity _item;
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_item = new RecordEntity(_tmpId);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}
我在我的 Android Studio 应用程序中使用 Room,当没有记录可供查询时,代码 A 会崩溃
使用Code B查询Room时没有记录怎么办?
@Dao
interface RecordDao {
// Code A
@Query("SELECT * FROM record_table where id=:id")
fun getByID(id:Int): Flow<RecordEntity>
// Code B
@Query("SELECT * FROM record_table")
fun getAll(): Flow<List<RecordEntity>>
}
如果您查看 room 为 RecordDao_Impl class RecordDao 实现生成的代码,您会注意到很多事情:
- 当 table 中不存在匹配记录时,getById 函数代码 return 为空,并且由于您的 'Code A' 函数 return 类型不为空,kotlin 抛出第一个函数的 NullPointerException。
- getAll 函数代码 return 是一个带有 ArrayList 的 Flow 对象,如果它找到任何记录,则会将它们添加到列表中,否则它只会将空的 ArrayList 发送到 Flow 对象,因此,您无论 room 是否找到匹配的记录,都会得到一个包含列表的流对象,因此不会抛出异常。
如果您在此处查看为这两个函数生成的代码,您可以更深入地理解这一点:
@Override
public Flow<RecordEntity> getByID(final int id) {
final String _sql = "SELECT * FROM record_table where id=?";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, id);
return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<RecordEntity>() {
@Override
public RecordEntity call() throws Exception {
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
final RecordEntity _result;
if (_cursor.moveToFirst()) {
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_result = new RecordEntity(_tmpId);
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}
@Override
public Flow<List<RecordEntity>> getAll() {
final String _sql = "SELECT * FROM record_table";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<List<RecordEntity>>() {
@Override
public List<RecordEntity> call() throws Exception {
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
final List<RecordEntity> _result = new ArrayList<RecordEntity>(_cursor.getCount());
while (_cursor.moveToNext()) {
final RecordEntity _item;
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_item = new RecordEntity(_tmpId);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}