You can use AutoMigrationSpec to give Room the additional information that it needs to correctly generate migration paths. Define a static class that implements AutoMigrationSpec in your RoomDatabase class and annotate it with one or more of the following: @DeleteTable. @RenameTable.
The common reasons for using database migration are: Upgrading to the latest version of the database software to improve security and compliance. Moving existing data to a new database to reduce cost, improve performance, and achieve scalability.
What are the advantages of migration tools? Migrations are helpful because they allow database schemas to evolve as requirements change. They help developers plan, validate, and safely apply schema changes to their environments.
Using AWS DMS to migrate data to AWS is simple. You start by spinning replication instances in your AWS environment, and then AWS DMS connects the source and target database endpoints. You can choose what you want to migrate—DMS allows you to migrate tables, schemas, and whole databases.
Room does NOT have a good Migration System, at least not until 2.1.0-alpha03
.
So, until we have better Migration System, there are some workarounds to have easy Migrations in the Room.
As there is no such method as @Database(createNewTables = true)
or MigrationSystem.createTable(User::class)
, which there should be one or other, the only possible way is running
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
inside your migrate
method.
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
In order to get above SQL script, you have 4 ways
Basically, you have to write the above script that will match the script that Room generates. This way is possible, not feasible. (Consider you have 50 fields)
If you include exportSchema = true
inside your @Database
annotation, Room will generate database schema within /schemas of your project folder. The usage is
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
Make sure that you have included below lines in build.grade
of your app module
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
When you run or build the project you will get a JSON file 2.json
, which has all the queries within your Room database.
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
So, you can include the above createSql
within you migrate
method.
If you don't want to export schema you can still get the query by running or building the project which will generate AppDatabase_Impl.java
file. and within the specified file you can have.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
Within createAllTables
method, there will be the create scripts of all the entities. You can get it and include in within you migrate
method.
As you might guess, Room generates all of the above mentioned schema
, and AppDatabase_Impl
files within compilation time and with Annotation Processing which you add with
kapt "androidx.room:room-compiler:$room_version"
That means you can also do the same and make your own annotation processing library that generates all the necessary create queries for you.
The idea is to make an annotation processing library for Room annotations of @Entity
and @Database
. Take a class that is annotated with @Entity
for example. These are the steps you will have to follow
StringBuilder
and append "CREATE TABLE IF NOT EXISTS "class.simplename
or by tableName
field of @Entity
. Add it to your StringBuilder
@ColumnInfo
annotation.
For every field, you have to add id INTEGER NOT NULL
style of a column to your StringBuilder
.@PrimaryKey
ForeignKey
and Indices
if exists.public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
Then, you can use it as
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
I made such a library for myself which you can check out, and even use it in your project. Note that the library that I made is not full and it just fulfills my requirements for table creation.
RoomExtension for better Migration
Application that uses RoomExtension
Hope it was useful.
By the time of writing this answer, room version was 2.1.0-alpha03
and when I emailed developers I got a response of
It is expected to have better Migration System in
2.2.0
Unfortunately, we still lack better Migration System.
Sorry, Room doesn't support auto-creation of tables without data loss.
It is mandatory to write the migration. Otherwise, it'll erase all the data and create the new table structure.
For anybody out there still looking for solutions to this issue, I have some good news. Room is starting to support Auto-migrations with version 2.4.0
https://developer.android.com/jetpack/androidx/releases/room#2.4.0-alpha01
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With