Here is my code:
public class DBHelper extends SQLiteOpenHelper {
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("sql-query");
try {
//db = getWritableDatabase();
fillAllDB(db);
} catch (JSONException e) {
e.printStackTrace();
}
}
// some code
}
fillAllDB(db); method adds a record to the table, but I can't use db = getWritableDatabase(); before method call - this is causing the looping. What to do in this case?
OnCreate method gives you writable database only, so no need to get the writable database, when you call the writable/readable database, sqlite framework checks whether database exist or not, if not then it will call the onCreate method, that why this is recursive, you should not call getWritable/getReadable database in onCreate/onUpgrade method of the SqliteOpenHelper class
Use the SQLiteDatabase db argument passed to your onCreate() method as the database to call your operations on.
getWritableDatabase() and getReadableDatabase() will invoke your onCreate() in case the database file did not exist, and calling get...Database() recursively while the previous call is still being processed causes this exception.
Also, catching exceptions in onCreate() is not a good idea. If there's a problem, the onCreate() method should not return normally - that tells the framework that the database setup was successful.
Related
In my app I want to initialize some data stored in a SQLite database.
But it turns out the SQLiteOpenHelper onCreate method is not called when I read my database (it is when I write into my database).
My app crash when I read the db for a table that does not exist (it does not crash if I create the table before). I could catch the exception but does not seem very clean to me.
Is it the normal behavior regarding SQLiteOpenHelper onCreate method or am I missing something?
Here is the initialisation function called in activity OnCreate()
private void InitializeDbPlayerList() {
SQLiteDatabase db;
Cursor cursorPlayers;
DbPlayerData dbPlayerData;
db = mGameDbHelper.getReadableDatabase ();
// The following line crash the app if PLAYER_TABLE_NAME does not exist
cursorPlayers=db.query(GameDatabaseOpenHelper.PLAYER_TABLE_NAME,
GameDatabaseOpenHelper.player_columns, null, new String[] {}, null, null,
null);
cursorPlayers.moveToFirst();
for(int j=0;j<cursorPlayers.getCount();j++)
{
dbPlayerData = new DbPlayerData(cursorPlayers.getString(0),cursorPlayers.getFloat(1),cursorPlayers.getFloat(2),
cursorPlayers.getInt(3),cursorPlayers.getInt(4));
mDbPlayerList .add(dbPlayerData);
}
}
Thx
Fabien
I'm using a single sqlite database throughout my app. So I want to wrap a connection to the db in a singleton for convenience. At first I thought I could keep a reference to the SQLiteDatabase around for that:
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(appContext); // local
myGlobalSQLiteDatabase = helper.getWritableDatabase(); // global
...
void someFunction() {
try {
myGlobalSQLiteDatabase.insertOrThrow(...);
} catch (Exception ex) {
}
}
but this would result in errors such as:
(1802) os_unix.c:30011: (2) stat(/data/data/com.me.test/databases/test.db) -
(1802) statement aborts at 16: [INSERT INTO mytable(f1,f2) VALUES (?,?)]
android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 1802)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:775)
...
(this is all being done on the main thread, a single test).
My second attempt was to instead keep a global reference to the helper only:
myGlobalSQLiteOpenHelper helper = new MySQLiteOpenHelper(appContext); // global
...
void someFunction() {
SQLiteDatabase db = myGlobalSQLiteOpenHelper.getWritableDatabase();
try {
db.insertOrThrow(...);
} catch (Exception ex) {
} finally {
db.close();
}
}
and that works. I have to call getWritableDatabase() and close() on each call of someFunction().
I don't know how much overhead there is in getWritableDatabase() and close(), I was originally hoping for the fastest implementation possible, as I'll be calling someFunction() repeatedly in response to user input. Is the second method the best option for this setup?
Thanks
You don't need to write getwritable database again and again just make a constructor of db class public DBCustomer open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
and call all the function of db just decalring object and calling object.open function
EDIT
First activity opens a database: I used the code
LoginDbAdapter mDbHelper; // as a data member
called
// in my onCreate() of my main activity login
mDbHelper = new LoginDbAdapter(this);
then in my
public void onResume(){
mDbHelper.open(); // opens only when the activity is resumed
super.onResume();
}
then I do the same thing above in my second activity to add a user. This worked.
My issue is as follows:
**How do i open a link to a second table in my database to access
a users information only. And where do i close it. **
UPDATE
an alternative way that works much better is initializing my DbAdapter in the onResume and then calling DbAdapter.open(); only when i need access to the db and closing it right after the work is done with DbAdapter.close();
note: it is also important to call startManagingCursor(cursor); and stopManagingCursor(cursor);
Might these helps:
find these where you getting writeable permission like these::
SQLiteDatabase db=this.getWritableDatabase();
Now wat you need to do iz::
db.insert(TABLE, null, values);
db.close();//put these after inserting your database;
You need to go in to your DATABASEADAPTER class
then close the database connection after insertion as per above code
in your Activity
mDbHelper= new DatabaseAdapter(this);
and in your insert method of DatabaseAdapter class
SQLiteDatabase db = this.getWritableDatabase();
and at last in your insert method call db.close();
You need to Edit these line inside your LoginDbAdapter inside close() method;
public class LoginDbAdapter
{
// close the database
public void close(){
if(mDbHelper != null){
mDbHelper.close();
mDb.close;//insert these line ;these close sqlitedatabase;
}
}
}
give the command to close inside a try{} catch{}
I'm getting two contradicting Exceptions when creating and populating my new SQLiteDatabase in Android. In short my code:
SQLiteOpenHelper extending class:
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_TABLE_CREATE);
loadLevelData(db); //puts data in the database
//db.close(); <<< ?
}
In my activity class I instantiate this class (in onCreate()), and call getWritableDatabase():
dbHelper = new DbOpenHelper(getApplicationContext());
database = dbHelper.getWritableDatabase();
Now if I don't call db.close() after populating the database, like above, I get
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
However if I DO close it, I get the following exception:
java.lang.IllegalStateException: database not open
on getWritableDatabase().
This really confuses me, so could anyone help me with what's wrong?
You are not expected to close the database in the DatabaseHelper class. However you need to close it every time you open it calling getWritableDatabase:
dbHelper = new DbOpenHelper(getApplicationContext());
database = dbHelper.getWritableDatabase();
//... do something with database
database.close();
You are closing your database at the wrong time.
I typically keep the database around like this:
public class MyActivity extends Activity {
SQLiteDatabase writeableDb;
// ...
// Code
// ...
public void onStart(){
super.onCreate(savedState);
// Do stuff, get your helper, etc
writeableDb = helper.getWriteableDatabase();
}
public void onStop(){
writeableDb.close();
super.onStop();
}
}
Alternatively, wrap all your code working with that db connection in a try/finally block
db = helper.getWriteableDatabase();
try { // ... do stuff ... }
finally { db.close(); }
Note: All of the opening/closing should be done in the Activity working with the database, not the open helper.
I've got custom adapter class, which incapsulates SQLiteDatabase. Adapter manages db connection:
public AutoDBAdapter(final Context context){
this.context=context;
checkDatabase();
try{
openDB();
}catch(Exception e){
e.printStackTrace();
}
checkDatabase()
method checks if DB exists and copies it from assets if necessary.
private void openDB() throws SQLException{
if(db==null)
db=SQLiteDatabase.openDatabase(dbFileName, null, SQLiteDatabase.OPEN_READWRITE);
}
I create AutoDBAdapter class inside my Activities.
I used this approach because I need my DB to be accessible from multiple activities. I know that that's not a good to do it.
My question: when should I close DB connection?
Any suggestions would be useful. Thanks.
If the db isn't used that often you should close it after each operation. If you are going to use it alot and want to keep it open, you should close it in the onPause method of the Activity.