I have huge DB, written with SQLiteOpenHelper. Now we are starting to implement Room to our project. So, my question is: how to be with migration problem?
For example, I have version number 100 in MySQLiteOpenHelper. I'm trying to migrate one table (and there are many other tables in DB) to Room.
I've create MIGRATION_100_101 in
MyDatabase : RoomDatabase (#Database(version = 101) class. So, I need to increase version in MySQLiteOpenHelper to 101 and make sure, that MyDatabase with migrations will be called before MySQLiteOpenHelper?
Is there any other way to have both SQLiteOpenHelper and RoomDatabase in one app?
AFAIK Room manages a separate database by itself and there isn't a great way to maintain a custom sqliteopenhelper and a room database. What we did was that we migrated subsets of the tables at once from old sqlite to room (basically, tables that need to be joined together for whatever reason), and kept two separate databases until all of the tables were migrated.
Depending on your situation, might be more painless to do a one-time migration for everything.
The only solution, that allows us to do this is next. Let's imagine, that current DB version is X and we are planing to migrate to version X+1.
Create SQLiteOpenHelper object that will drop all tables, if the current DB version is X and recreates all NOT migrated tables for version X+1. We need to call getReadableDatabase/getWritableDatabase method so, table creation (methods onCreate/onUpgrade) takes place. This SQLiteOpenHelper object will be temporary.
Create RoomDatabase object for version X+2 with fallbackToDestructiveMigration. This will clear all migrated tables and recreates them. Also, we need to call getReadableDatabase/getWritableDatabase for creation take place. This RoomDatabase object is temporary too.
So, on this moment we have already created DB: part of the tables (that are not migrated) will be created by SQLiteOpenHelper, other - by RoomDatabase.
Create RoomDatabase object for version X+2 without fallbackToDestructiveMigration. And this object we are going to use in our application.
Create SQLiteOpenHelper object for version X+2, that will just use created DB (migration from X+1 to X+2 are not required at all, because tables was created by Room at step 2). And this object we are going to use in our application.
Related
I was reading this article (http://www.vogella.com/tutorials/AndroidSQLite/article.html) to learn about SQLite databases in android apps.
In the article he has a tip:
It is good practice to create a separate class per table. This class defines static onCreate() and onUpgrade() methods. These methods are called in the corresponding methods of SQLiteOpenHelper. This way your implementation of SQLiteOpenHelper stays readable, even if you have several tables.
if I understand this tip correctly I should have a class for each table that I have in my database?
Is that really the best practice?
If so, what about complex queries that uses multiple tables? how do I manage that if the creation is in different classes?
How do I correctly keep the database version? for each table change I will change the database version number?
Thanks
SQLiteOpenHelper manages database files, not tables. You manage the tables yourself with the given database lifecycle callbacks (onCreate(), onUpgrade()).
Quickly reading one could interpret that the author advocates creating a separate database helper for each table (I did at first), but that's not the case. That would have been bad advice.
To reiterate the author's intent:
One database helper class.
The helper involves separate table-specific helper classes which are not SQLiteOpenHelpers but just doing part of the work for the top-level database helper.
I am creating a simple application that uses a database derived from db = SQLiteDatabase.openOrCreateDatabase(...). Now, when I create it I use db.setVersion(1);
And I read somewhere that I have to change the database version each time I change it. Now I can't find the particular tutorial where I read this, so I am left with some questions.
1)What is the reason behind versioning of a database? What is a practical purpose?
2)When exactly should the version be updated? After every insert? Every additional table added?
3)Will I be in trouble if I don't update the versions after 1? What would it lead to?
1)Versioning the database is really versioning your schema. This allows you to know when the schema is changed so you can convert it.
2)Whenever you change the schema.
3)If you change the schema, you won't know which one is being used and will end up with exceptions. If you never change the schema, nothing will happen.
And you shouldn't be manually calling setVersion. It already knows the version for an existing one, and you pass in the version elsewhere if its a new database.
The SQLite Database Version In Android is only neccessary if you manage database creation and version updates with the SQLiteOpenHelper.
SQLiteOpenHelper takes care of
opening the database if it exists,
creating it if it does not exis,
upgrading its schema if necessary
sets the SQLite Database Version.
The databaseverionnumber is set in the SQLiteDatabase-constructor.
Your example SQLiteDatabase.openOrCreateDatabase(...) does not use SQLiteOpenHelper so in this case there is no need set the dbversion.
In my android app, I was using a standard SQLite database with a helper class that had 1 table with 3 columns. In the most recent update I had to add another column of to the table, but some users have reported crashes, which (judging by the stack trace) I think comes from the new version trying to read from a column that does not exist because the data is from the old version. How can I protect the users' data between updates short of a manual backup and restore?
Here is the link to the complete updated database class:
https://github.com/cjbrooks12/scripturememory/blob/working/src/com/caseybrooks/scripturememory/databases/VersesDatabase.java
SQLiteOpenHelper will handle the database versioning, you will just have to provide it with proper database version numbers and overridden callbacks. Looking at your code:
Your DB_VERSION is 1. When you change the database schema between released versions, you should increment this number. The version number is stored in the database file, and if the version provided in code is different from the one stored in file, onUpgrade() or onDowngrade() will be called accordingly. In your case, since the database file already exists, no onCreate() was called and since the version numbers matched, no upgrade was performed.
Your onUpgrade() drops the table and then recreates it. In some cases this might be ok, say, it's just a cached copy of data stored elsewhere, but usually as a user, I don't want an app upgrade to delete my data. Implement onUpgrade() so that it does the necessary schema modifications while preserving data. Some generic strategies for this:
If it's just adding some columns ALTER TABLE and put some suitable default values.
If it's more complex schema change, rename the old tables to temporary names, create new tables and then migrate data from the temp tables.
In any case, after onUpgrade() the database schema should be in the same shape it would be if onCreate() was called to create a new database, but with existing data preserved.
I have an app which requied more than one table.
The DB is mosly for read purposes and i want to know what is the best way to manage my tables.
I tought about 2 options.
Create new DB class with new DB for each table.
Create new table in the exits DB.
What is the best for better performance in reading?
hat is the best for better performance in reading?
For sure don't create new database but put all tables you need in one database. Reasons are more there, for instance now you don't know whether you will need sometime in a future to create some relations between these tables.
I's not "good" to have more db files which will represent one table, it's not comfortable and efficient as well. So my suggestion to you is to keep only one db file and put all tables in this one.
The best approach to manage SQLite database is to use SQLiteOpenHelper class that wraps all required logic for reading and writing from/to database. Then, SQLiteDatabase itself provides some API methods for inserting, updating and deleting from db.
At the end as my personal recommendation. If you'll have more than one table just how i mentioned create one SQLiteOpenHelper subclass for creating database and then for each table create object that will represent table "in objects" e.q. columns in table will become properties of object.
Finally for each table create DAO classes that will wrap CRUD operations and some specific methods for each table.
If you don't know how to start check these tutorials:
Android SQLite Database and ContentProvider - Tutorial
Android SQLite Database Tutorial
You can use SQLiteDatabase.
SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.
Database names must be unique within an application, not across all applications.
Read: Documentation
I don't exactly know how android updates the applications. As far as I've read around here it keeps the SQLite database. So, imagine this scenario: one application that uses SQLite database for persisting data. After a while I release v2 which contains some database changes and I need to update user data in database. How can I make this during the update process ?
See SQLiteOpenHelper#onUpgrade. Subclass the SQLiteOpenHelper class and do all the stuff to update the tables in the onUpgrade method.
As you will see, the constructor of SQLiteOpenHelper takes as last parameter the Database version:
version: number of the database (starting at 1); if the database is older, onUpgrade(SQLiteDatabase, int, int) will be used to upgrade the database