I'm currently building an app which utilises the SQLite Database in Android, I understand that the tables are set up when overriding "onCreate" in my subclass of SQLiteOpenHelper.
However, I want the database to be created with a set of default information and was wondering where it was conventional to insert this? Should I be doing this with SQL in onCreate, or later on by checking a preference such as "onFirstRun" and using my Helper class to insert some values in an Activity somewhere?
Any helps/tips appreciates, cheers.
I usually add default data on the OnCreate of the class that extends SQLiteHelper like this, because its only does once (unless you uninstall the app) and it is quite clear and easy:
public class XXX extends SQLiteOpenHelper {
String sqlCreate = "CREATE TABLE X (codigo INTEGER, nombre TEXT)";
String sql ="Insert into X ....";
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(sqlCreate);
db.execSQL(sql);
}
It is better to insert default information in onCreate of SQLiteOpenHelper if you haven't released your app already to store. If already released do it in onUpgrade of SQLiteOpenHelper by making the necessary validations. This way all the code related to db stays together and you can manage the upgrade scenarios gracefully.
Related
I am breaking out each SQLite table's code (including initial construction of the table as well as operations on that table) into separate classes extending SQLiteOpenHelper.
In order to get these tables to be created (that is to say, to get the onCreate() method to be called), I have to increment the DATABASE_VERSION (see my own answer here for the details).
But with this methodology, I end up with different version numbers for each class/table - I had to set the DATABASE_VERSION value for the second table I created to 2, I will have to set the third one to 3, etc.
So I will end up with multiple different version values for the same DATABASE (*.db file). If they are all the same val, the onUpgrade() method does not get called, and thus, the onCreate() method is not called, and thus the new table is not created.
Is this "okay" - having a database with several different simultaneous version numbers?
The only other (reasonable) option I know of is to put all the DB code (covering multiple tables) into a single class that extends SQLiteOpenHelper - is doing so actually the preferred method? IOW, is my separation of the db code into several classes, one for each table, a help or a hindrance?
UPDATE
So this is my non-destructive way (by inserting "IF NOT EXISTS" into the DDL) to gradually add new tables, using, per CommonsWare's advice, just one class that extends SQLiteOpenHelper:
#Override
public void onCreate(SQLiteDatabase db) {
String CONDITIONALLY_CREATE_VENDORS_TABLE = "CREATE TABLE IF NOT EXISTS " +
TABLE_VENDORS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_VENDORID
+ " TEXT," + COLUMN_COMPANYNAME + " TEXT" + ")";
db.execSQL(CONDITIONALLY_CREATE_VENDORS_TABLE);
// add more tables as needed following the pattern above
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//db.execSQL("DROP TABLE IF EXISTS " + TABLE_VENDORS); <= Only need to DROP if the table's structure changes; so comment such a line out for the particular table in that case
onCreate(db);
}
NOTE: Whenever I do add a new table, I have to "up" (increment) the DATABASE_VERSION value, so that onUpgrade()/onCreate() are called.
I am breaking out each SQLite table's code (including initial construction of the table as well as operations on that table) into separate classes extending SQLiteOpenHelper
It is important, for thread safety among other reasons, to have a single instance of SQLiteDatabase that you use consistently. That in turn, will require you to have a single SQLiteOpenHelper class. The exception would be for totally independent database files (one SQLiteHelper per database), but that's not usually needed.
Is this "okay" - having a database with several different simultaneous version numbers?
That is not "okay" at all. The highest number wins.
The only other (reasonable) option I know of is to put all the DB code (covering multiple tables) into a single class that extends SQLiteOpenHelper - is doing so actually the preferred method? IOW, is my separation of the db code into several classes, one for each table, a help or a hindrance?
Breaking out "the db code into several classes, one for each table" is not necessarily a problem. What is a problem is having them be independent subclasses of SQLiteOpenHelper.
Let's say that you want these classes not merely to handle table creation and upgrades, but also other CRUD operations related to the table. Having a dedicated class for that is fine. However, the table creation and upgrade logic needs to be driven by a single SQLiteOpenHelper class. Simply have onCreate() and onUpgrade() on your SQLiteOpenHelper delegate the actual work to the per-table classes. This way, you get your code organization, without having multiple SQLiteOpenHelper classes.
When there is new data available to my Android application I need to completely remove all current entries in one of the SQLite database tables and replace them all with the new data. What is the best way to do this?
Would it be best to run
DELETE * FROM my_table
or
run a delete query for every row in the database
or run
database.execSQL(DATABASE_DROP_MY_TABLE);
database.execSQL(DATABASE_CREATE_MY_TABLE);
Where DATABASE_DROP_MY_TABLE is SQL to drop the table and DATABASE_CREATE_MY_TABLE is
SQL to create the table again with no entries.
And then following one of these, insert the new data.
Of course there are probably other ways to do this that I have not thought of.
Assuming you're using SQLiteOpenHelper, you can just close db, delete the whole file and recreate the db:
class MyDatabase extends SQLiteOpenHelper {
public static final String DB_NAME = "wat";
public MyDatabase(Context context) {
super(context, DB_NAME, null, CURRENT_VERSION);
}
}
dbHelper.close(); // dbHelper is your MyDatabase instance
context.deleteDatabase(DB_NAME);
SQLiteDatabase db = dbHelper.getWritableDatabase() // will create empty db
Nice thing about this solution is that you won't have to update table resetting code when you add new tables to your schema. It also correctly recreates indexes you might have added.
I wouldn't complicate things, and simply drop the table with DROP TABLE statement. As the doc say:
The SQLite DROP TABLE statement is used to remove a table definition and all associated data, indexes, triggers, constraints and permission specifications for that table.
You would have clean plate, then create the table again and add your new data.
I'm new to programming. I'm making an Android app and I am at a new hurtle. I am using the SQLiteOpenHelper class to manage my database. Its been great, I am able to create tables, add entries and all that good stuff.
The problem I have is that for one of my tables I want to have an initial 7 entries that keep the same ID and can be replaced by the user. My plan is to use a SQLiteDatabase.replace() method in order to replace these entries. Since I want the entries to be set by me and then edited by the user, that means I want to add entries using the SQLiteOpenHelper class so that these entries are set only when the user installs the app and creates the database. I do not want to make a pre-populated database that I must include in the install package.
My Java skills are god awful so my main question is how do I add entries from inside my SQLiteOpenHelper class? I already know how to add entries in my other classes using the following method that I made:
public long createCategoriesSQLEntry(String name) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_CATEGORIES, name);
return myDatabase.insert(StringCategory_Table, null, cv);
}
Override the onCreate() in the database helper. Like this.
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
try{
if(db.isOpen()){
//create tables here
db.execSQL("create table");
db.execSQL("insert row");
db.execSQL("insert row");
}
}
You are database will be installed when for the first time your application is installed. So, you write you data either in file and load it on onCreate method in SQLiteHandling class or just write the data in your java and call it in onCreated method like CyberTengu said.
I have a project with a set of classes that are responsible for their respective database tables.
Each table managing class contains CRUD methods that follow the pattern of get connection, run crud operation, close connection:
public class PersonManager {
SQLiteDatabase db;
DbAdapter dbAdapter; //This is a subclass of SQLiteOpenHelper
public void addPerson(Person person)
{
ContentValues contentValues = new ContentValues();
contentValues.put("email", person.email);
contentValues.put("first_name", person.firstName);
db = dbAdapter.getWritableDatabase();
db.insert("person", null, contentValues);
db.close();
}
...other crud/utility methods omitted...
}
Now that I am upgrading my database via onUpgrade(), I run into database locked issues.
The exact error message follows:
CREATE TABLE android_metadata failed
Failed to setLocale() when constructing, closing the database
android.database.sqlite.SQLiteException: database is locked
It appears that onUpgrade is either meant to:
1 run db.execSQL() calls or
2 use helper classes that use onUpgrade()'s SQLiteDatabase rather than their own
It would be much easier to use my table managing classes to migrate data in onUpgrade() than db.execSQL() statements, or rewrite all my CRUD methods to take onUpgrade()'s SQLiteDatabase.
Am I setting up my database access correctly? If the above code follows the correct pattern, what should I do to fix this issue?
Thanks!
Here's your problem:
db = dbAdapter.getWritableDatabase();
When you're in onUpgrade(), you have to use the SQLiteDatabase handle that onUpgrade() provides you. So your solution is to rewrite your addPerson function to take one more argument -- an SQLiteDatabase handle:
public void addPerson(Person person, SQLiteDatabase db) {...}
If you need to call addPerson() from elsewhere in your project, then keep your current addPerson(Person person) function, have it do that
db = dbAdapter.getWritableDatabase()
call, and pass db to your two-argument version of addPerson().
I didn't get any answers, so I asked on a dev hangout.
According to the Android Developer Hangout Team, onUpgrade is only meant for structure alterations, not really for data migration/manipulation.
Friends,
I have an existing apps published and during an upgrade, I want to add a new table to my database, but also not lose the data from the other tables when upgrading the application. Can someone tell me, (but if you could show me some example also) of how this is done and how to test it. Because I've looked through the forums but mainly there are discussions about adding a new column etc. I figured that I have to do it somehow with alter table, but I did not understand everything. If you can tell me the steps of this process I would really appreciate it.I have used DBAdapter class extends SQLiteOpenHelper.Accept my question and asap give me solution..
Everything happens in your class DBAdapter. There you must implement a method onUpgrade which adds your new table to the database. Here is a skeleton for doing this:
class DBAdapter extends SQLiteOpenHelper {
// Implement the other methods
// This method is called when your application is being upgraded.
public void inUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "adding table to the database") ;
db.execSQL("CREATE TABLE MyNewTable(_id INTEGER, name TEXT)") ;
Log.i(TAG, "upgrade done") ;
}
You may look at the documentation of the class SQLiteOpenHelper