I have been going through Room DB introduced in new architecture components in Android and thinking about migrating my current DBs to Room DBs.
But my current db implementation allows me to add columns to the table but as per Room, fields in POJO class represents the columns of table.
It is possible to add columns in Room DB using raw query, if yes, how shall I implement it.
I know this is an old post, but this might help someone out there that needs help with this.
Do you want to add said column on an upgrade of a DB or would you like to do it on first creation of the table?
If you want to do it on an upgrade of the DB then you can look at
Migrating Room databases
Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, `name` TEXT, PRIMARY KEY(`id`))");
}
};
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
#Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Book ADD COLUMN pub_year INTEGER");
}
};
If you want to add the column on the fly you will have to get the instance of your DB then can try call the following:
getDatabaseInstance().query()
There is little point for using Room with this table. After all, you cannot dynamically modify any entities or DAO methods, and so Room will not know anything about these changed columns.
If the rest of your database is Room-friendly, and you just have this one weird table, you can call getOpenHelper() on your RoomDatabase to get the SupportSQLiteOpenHelper, then work from there. The SupportSQLite... classes resemble the native Android SQLite API.
Related
I need to know how to "DROP FROM Table" using Room Persistence Library.
I already know that we can delete all the rows using the method:
#Query("DELETE FROM table")
void deleteAll();
However, what I need is deleting the whole table. This is because of my primary_key is an autoincrement column, so using the previous code, it is not rested.
I already read answers about this topic in the next links:
Reset auto-increment in Android's Room library
Android Room - reset auto generated key on each app run
However, I can't believe that this library doesn't provide an easier way to do this, regardless of the reason or use.
Could use Migrations that Room provides for updating the database via our own queries. As we want to make changes to the database which Room cannot resolve (yet) from the code. We could delete the table, recreate it or update it. Depending on what is needed.
Option 1: Migrate with keeping other data
First increase the version of the database: update the version parameter in the #Database annotation.
Create a migration like this:
static final Migration MIGRATION_1_2 = new Migration(1, 2) { // From version 1 to version 2
#Override
public void migrate(SupportSQLiteDatabase database) {
// Remove the table
database.execSQL("DROP TABLE my_table"); // Use the right table name
// OR: We could update it, by using an ALTER query
// OR: If needed, we can create the table again with the required settings
// database.execSQL("CREATE TABLE IF NOT EXISTS my_table (id INTEGER, PRIMARY KEY(id), ...)")
}
};
Add the migration when building the database:
Room.databaseBuilder(context, MyDatabase.class, "mydatabase")
.addMigration(MIGRATION_1_2) // Add the migration
.build();
Run the app again. If the queries were correct, the migration is done
Option 2: Migrate with losing data
There is also a fast option, but all data in the database will be cleared!
This is because the database gets recreated when using the method below.
Like option one, increment the version of the database
Use .fallbackToDestructiveMigration() when creating the database, like so:
Room.databaseBuilder(context, MyDatabase.class, "mydatabase")
.fallbackToDestructiveMigration()
.build();
Run the app. It will remove the old database and recreate it. (All earlier data is wiped)
If you want to do this with auto migration then need to use spec as autoMigrations value for #Database annotation. Look like
this
autoMigrations = {#AutoMigration(from = 1, to = 2, spec = AppDatabase.MyAutoMigration.class)}
Example like you want to delete a table(YourTableName) from database version 1 and then migrate to version 2 then the full code looks like this
#Database(
version = 2,
entities = {Entity1.class, Entity2.class},
autoMigrations = {#AutoMigration(from = 1, to = 2, spec = AppDatabase.MyAutoMigration.class)},
exportSchema = true)
#TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
#DeleteTable.Entries(value = #DeleteTable(tableName = "YourTableName"))
public static class MyAutoMigration implements AutoMigrationSpec {
}
// Your DAO 1
// Your DAO 2
}
I am trying to migrate my database over to use Android's Room Architecture. However I have some complex sqlite View's in my application. I don't see any information or documentation on how to create a view with room. Can anyone give me examples or point to tutorials?
You can use androidx.room.DatabaseView annotation
Example from documentation:
#DatabaseView("SELECT id, last_name FROM User")
public class UserSummary {
public long id;
#ColumnInfo(name = "last_name")
public String lastName;
}
A view in sql is just a live updating query. Using LiveData you can get the live updates, and you can simply create a new entity to use specifically for your view. This class will hold all the data your view will. Then in your entities DAO you paste your sql query associated with the view.
As of now, there is an open issue in Android Room to support Database Views in the state of Fixed, perhaps waiting for creators to support it would be a good call.
although using a hacky method you might get it done:
You may create an #Entity similar to your view (in columns) then onCreate of the database drop the table generated for this Entity.
Room
.databaseBuilder(context, DueDatabase.class, DB_NAME)
.addCallback(new RoomDatabase.Callback() {
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
//Drop the fake table and create a view with the same name
db.execSQL("DROP TABLE view_name");
db.execSQL("CREATE VIEW view_name " +
"AS SELECT [...]"
);
}
})
.build();
this way room would let you use the view name in queries and map the retrieved data on your #Entity class correctly,
although you have to keep in mind that this approach will break the migration.
for migrations to work you have to find a workaround (maybe drop your view and recreate the fake table might work)
I'm writing an android app where I have a java class which should represent a Table in DB.
class Table1 {
String row1;
String row2;
}
If I have to create a table in database I should do something like this.
mydatabase.execSQL("CREATE TABLE IF NOT EXISTS Table1(row1 VARCHAR,row2 VARCHAR);");
But the problem here is I'm duplicating the class structure in the SQL query. This is error prone and will require changes at multiple places whenever I need to change the attributes of the table. Is there a better way to do this. Something like mydatabase.createTableFrom(Table1.class) that I could use instead?
About the update of SQLite in Android.When you change the structure of the datebase,how can we update the datebase without delete the data?
You should override the onUpgrade Method in the SQLiteOpenHelper. You should code something like this.
public void onUpgrade (SQLiteDatabase db,int oldVersion,int newVersion){
String update = ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
db.execSQL(update);
}
Dropping a table, adding a row, inserting/updating/deleting data should be done here.
Alter Table gives you very limited options in performing an update to the database tables. If you want to copy your data into a completely new structure, you should think about creating temporary tables where you can copy data, create the new schema and then copy your data from the temporary tables to the new table, in this upgrade method.
Make sure you have your DB Version numbers correctly updated while creating the DBHelper.
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.