在 android 递归调用的 getDatabase 中获取异常
Getting exception in getDatabase called recursively in android
我正在尝试在 android 中为我的项目实现 DBHelper,我是如何实现它的
我想做的是,在运行时决定要为此创建哪个数据库我实现了 class abstract class SQLiteDBService
extends SQLiteOpenHelper
它由两个 classes LocalSQLiteDBService
和 RestServerSQLiteDBService
运行时继承,我决定调用哪个 override
classes 中的 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);
}
}
下面是我的 class 的代码,它将覆盖 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 中,您传递了一个可写的数据库。使用那个,并将其传递给您的辅助函数。没有你的辅助函数请求一个新的。
我正在尝试在 android 中为我的项目实现 DBHelper,我是如何实现它的
我想做的是,在运行时决定要为此创建哪个数据库我实现了 class abstract class SQLiteDBService
extends SQLiteOpenHelper
它由两个 classes LocalSQLiteDBService
和 RestServerSQLiteDBService
运行时继承,我决定调用哪个 override
classes 中的 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);
}
}
下面是我的 class 的代码,它将覆盖 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 中,您传递了一个可写的数据库。使用那个,并将其传递给您的辅助函数。没有你的辅助函数请求一个新的。