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 有效吗?的主要内容,如果未能解决你的问题,请参考以下文章

sql注入靶场搭建

sqli-less5

搭建sqli靶场

sqli-labs less33 GET- Bypass AddSlashes (GET型绕过addslashes() 函数的宽字节注入)

sqli-labs(9-10关)

ThinkPHP 3.1.3及之前的版本使用不当可造成SQLi