java - 在 android 中递归调用 getDatabase 时出现异常

标签 java android sqlite illegalstateexception

我正在尝试在 android 中为我的项目实现 DBHelper,这里我是如何实现它的 我想做的是,在运行时决定要为此创建哪个数据库,我实现了类抽象类SQLiteDBService扩展SQLiteOpenHelper 它由两个类 LocalSQLiteDBServiceRestServerSQLiteDBService 继承,运行时我决定调用哪个类并覆盖两者中的onCreate方法具有不同数据库和表的类,

package db_service;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Iterator;
import db_table.TABLES;

/**
 * Created by Dipak on 3/5/2016.
 */
public abstract class SQLiteDBService extends SQLiteOpenHelper{

    private static final String TAG_DB_OPERATION    = "DB Operation";

    private static final int    DATABASE_VERSION = 1;

    private SQLiteDatabase  m_sqlLiteDatabase;

    public SQLiteDBService(Context context,String database_name) {
        super(context, database_name, null, DATABASE_VERSION);
        Log.i(TAG_DB_OPERATION, "Creating Database...");
    }

    public void OpenWrite() {
        m_sqlLiteDatabase = this.getWritableDatabase();
    }

    public void OpenRead() {
        m_sqlLiteDatabase = this.getReadableDatabase();
    }


    public void Close() {
        this.close();
    }

    //TODO:it will get called for every application launch
    public void CreateTable(JSONObject obj) {
        try {
            int i=0;
            JSONObject tables = obj.getJSONObject("tables");
            Log.i(TAG_DB_OPERATION ,"Tables:" + tables.toString());
            Iterator<String> table = tables.keys();
            while(table.hasNext()){
                String tableName = table.next();
                Log.i(TAG_DB_OPERATION,"Table Name:" + tableName);
                JSONArray tableColumns = tables.getJSONArray(tableName);
                Log.i(TAG_DB_OPERATION, "Table Columns:" + tableColumns.toString());
                String create_table_query = "create table " + tableName + "(";
                for(i = 0 ; i < tableColumns.length();i++) {
                    JSONObject column = tableColumns.getJSONObject(i);
                    Log.i(TAG_DB_OPERATION,"Column:" + column.toString());
                    create_table_query += column.getString("name") + " " + column.getString("type");
                    if(i != tableColumns.length()-1){
                        create_table_query += ",";
                    }
                }
                create_table_query += ");";
                CreateTable(create_table_query);
            }
        }
        catch (Exception e) {
            Log.i("DB Operation","Something wrong failed to create table");
        }
    }

    public void CreateTable(String createTableQuery) {
        Log.i(TAG_DB_OPERATION,"CreateTable" +createTableQuery);
        OpenWrite();
        m_sqlLiteDatabase.execSQL(  createTableQuery);
        Log.i(TAG_DB_OPERATION,"Done Creating Table");
    }

    public Cursor ReadTable(String tableName, String[] columns) {
        Log.i(TAG_DB_OPERATION,"ReadTable");
        OpenRead();
        return m_sqlLiteDatabase.query(tableName, columns, null, null, null, null, null);
    }
}

下面是我的类的代码,它将重写 onCreate 方法

package db_service;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import db_table.TABLES;

/**
 * Created by Dipak on 3/5/2016.
 */
public class LocalSQLiteDBService extends SQLiteDBService {
    private static final String TAG_LOCAL_DB_OPERATION = "DB Operation Local";

    private static final String DATABASE_NAME       = "LOCAL.DB";
    public LocalSQLiteDBService(Context context){
        super(context, DATABASE_NAME);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG_LOCAL_DB_OPERATION,"onCreate");
        //CreateTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.getJson());
        CreateTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.CREATE_TABLE_QUERY);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public boolean isCredentialsPresent() {
        Log.i(TAG_LOCAL_DB_OPERATION,"isCredentialsPresent");
        return GetStoredCredentials().getCount() != 0;
    }

    public Cursor GetStoredCredentials(){
        Log.i(TAG_LOCAL_DB_OPERATION,"isCredentialsPresent");
        String[] columns = {
                TABLES.LOCAL_DB.CREDENTIAL_STORE.ID,
                TABLES.LOCAL_DB.CREDENTIAL_STORE.USER_ID,
                TABLES.LOCAL_DB.CREDENTIAL_STORE.PASSWORD
            };
        return ReadTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.CREATE_TABLE_QUERY,columns);
    }
}

这是我的使用方法

LocalSQLiteDBService m_SqLiteDBServiceLocal;
m_SqLiteDBServiceLocal = new LocalSQLiteDBService(this);
m_SqLiteDBServiceLocal.isCredentialsPresent()

下面是我遇到的异常

03-06 14:21:59.816 30879-30879/? I/DB Operation Local: onCreate
03-06 14:21:59.816 30879-30879/? I/DB Operation: CreateTablecreate table credentials_store(id number,user_id number,password text);
03-06 14:21:59.817 30879-30879/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   Process: com.buk, PID: 30879
                                                   java.lang.RuntimeException: Unable to start activity ComponentInfo{com.buk/com.buk.MainActivity}: java.lang.IllegalStateException: getDatabase called recursively
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                       at android.os.Looper.loop(Looper.java:148)
                                                       at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                    Caused by: java.lang.IllegalStateException: getDatabase called recursively
                                                       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:203)
                                                       at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
                                                       at db_service.SQLiteDBService.OpenWrite(SQLiteDBService.java:33)
                                                       at db_service.SQLiteDBService.CreateTable(SQLiteDBService.java:77)
                                                       at db_service.LocalSQLiteDBService.onCreate(LocalSQLiteDBService.java:25)
                                                       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
                                                       at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
                                                       at db_service.SQLiteDBService.OpenRead(SQLiteDBService.java:37)
                                                       at db_service.SQLiteDBService.ReadTable(SQLiteDBService.java:84)
                                                       at db_service.LocalSQLiteDBService.GetStoredCredentials(LocalSQLiteDBService.java:45)
                                                       at db_service.LocalSQLiteDBService.isCredentialsPresent(LocalSQLiteDBService.java:35)
                                                       at com.buk.MainActivity.onCreate(MainActivity.java:51)
                                                       at android.app.Activity.performCreate(Activity.java:6237)
                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                       at android.os.Looper.loop(Looper.java:148) 
                                                       at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

最佳答案

如果 getWritableDB 已经在未关闭原始数据库的情况下被调用,则无法调用该方法。在 onCreate 中,您传递了一个可写数据库。使用该函数,并将其传递给您的辅助函数。不要让您的辅助函数请求新的辅助函数。

关于java - 在 android 中递归调用 getDatabase 时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35825116/

相关文章:

javascript - 使用javascript插入带有变量的SQLite

android - SQLite 和共享首选项的优缺点

javascript - 从 MySQL 检索数据到 JSP

android - 如何在 Android 上处理 Facebook ShareDialog.canShow() == false

java - eclipse 和路径

android - firebase-core 和 firebase-analytics 库有什么区别?

java - 找不到 fragment ID 的 View

sql - 我认为正确的外部连接可以解决这个问题,但是

java - 将小数转换为另一种基数的时间复杂度

java - 不属于您的应用程序的动画 Activity