isOpen 函数对 Room 数据库或 SQLite 有效吗?
Posted
技术标签:
【中文标题】isOpen 函数对 Room 数据库或 SQLite 有效吗?【英文标题】:isOpen function valid for Room database or SQLite? 【发布时间】:2021-11-26 15:59:40 【问题描述】:Package androidx.room 有这个函数,如果我连接到数据库,它应该返回。但我想确保这仅适用于 Room 和 NOT SQLite,我得到的都是错误的。
/**
* Returns true if database connection is open and initialized.
*
* @return true if the database connection is open, false otherwise.
*/
public boolean isOpen()
// We need to special case for the auto closing database because mDatabase is the
// underlying database and not the wrapped database.
if (mAutoCloser != null)
return mAutoCloser.isActive();
final SupportSQLiteDatabase db = mDatabase;
return db != null && db.isOpen();
【问题讨论】:
请您插入代码作为文本而不是图像 这些函数只适用于房间数据库,因为当我们创建 Room.databaseBuilder 的实例时,我们会得到这个方法来检查数据库。 【参考方案1】:是的,但是当您打开数据库时,您很可能会误解,因为您是错误的。
即构建 RoomDatabase 不会(除非您强制执行此操作)打开数据库。在需要之前,它会保持实际打开状态。只有在实际尝试访问数据库时才需要它。
考虑以下显示状态的内容:-
public class MainActivity extends AppCompatActivity
TheDatabase db;
AllDao dao;
List<Table1> table1List;
private static final String TAG = "MAININFO";
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try
Log.d(TAG, "Getting Room instance" + db.isOpen());
catch (Exception e)
e.printStackTrace();
db = TheDatabase.getInstance(this);
try
Log.d(TAG,"Getting DAO" + db.isOpen());
catch (Exception e)
e.printStackTrace();
dao = db.getAllDao();
try
Log.d(TAG, "Querying Table1 " + db.isOpen());
catch (Exception e)
e.printStackTrace();
table1List = dao.getAll();
try
Log.d(TAG, "After Query " + db.isOpen());
catch (Exception e)
e.printStackTrace();
@Database (TheDatabase) 类包含一个回调,该回调在调用 onOpen 或 onCreate 时写入日志。
运行时,日志包括以下内容:-
2021-10-07 06:40:49.037 D/MAININFO: Getting DAOfalse
2021-10-07 06:40:49.039 D/MAININFO: Querying Table1 false
2021-10-07 06:40:49.069 D/THEDATABSEINFO: onCreate has been called. For a.a.so69466269roomisopen.TheDatabase$1 a.a.so69466269roomisopen.TheDatabase$1@112c3ea Opencounter = 0
2021-10-07 06:40:49.075 D/THEDATABSEINFO: onOpen has been called. For a.a.so69466269roomisopen.TheDatabase$1 a.a.so69466269roomisopen.TheDatabase$1@112c3ea OPenCounter = 0
2021-10-07 06:40:49.080 D/MAININFO: After Query true
所以在查询之后 (即在实际访问数据库之后) isOpen 返回 true。在访问数据库之前,isOpen 返回 false。
第一次尝试(在获取实例之前)发出 NPE(正如预期的那样),因此消息不会写入日志。强制打开
现在考虑 @Database 类 TheDatabase,自从运行上述代码以来,它添加了以下行(在返回实例之前)。
instance.getOpenHelper().getWritableDatabase(); //<<<<< FORCE OPEN
这是完整的 TheDatabase 类(为强制修改):-
abstract class TheDatabase extends RoomDatabase
abstract AllDao getAllDao();
private static final String DATABASE_NAME = "thedatabase.db";
private static final String TAG = "THEDATABSEINFO";
private static volatile TheDatabase instance = null;
private static int counter = 0;
static TheDatabase getInstance(Context context)
if (instance == null)
instance = Room.databaseBuilder(
context,
TheDatabase.class,
DATABASE_NAME
)
.addCallback(callback)
.allowMainThreadQueries()
.build();
instance.getOpenHelper().getWritableDatabase(); //<<<<< FORCE OPEN
return instance;
static Callback callback = new RoomDatabase.Callback()
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db)
super.onCreate(db);
Log.d(TAG,"onCreate has been called. For " + this.getClass().getName() + " " + this + " Opencounter = " + counter);
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db)
super.onOpen(db);
Log.d(TAG,"onOpen has been called. For " + this.getClass().getName() + " " + this + " OPenCounter = " + counter++);
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db)
super.onDestructiveMigration(db);
;
现在运行日志时包括:-
2021-10-07 07:07:16.264 D/THEDATABSEINFO: onOpen has been called. For a.a.so69466269roomisopen.TheDatabase$1 a.a.so69466269roomisopen.TheDatabase$1@112c3ea OPenCounter = 0
2021-10-07 07:07:16.264 D/MAININFO: Getting DAOtrue
2021-10-07 07:07:16.266 D/MAININFO: Querying Table1 true
2021-10-07 07:07:16.271 D/MAININFO: After Query true
即一旦获得实例,isOpen
就会返回 true。
【讨论】:
谢谢!我对 isOpen 的理解是错误的,因为我认为这意味着我可以访问数据库实例。以上是关于isOpen 函数对 Room 数据库或 SQLite 有效吗?的主要内容,如果未能解决你的问题,请参考以下文章
sqli-labs less33 GET- Bypass AddSlashes (GET型绕过addslashes() 函数的宽字节注入)