In the first part of the Room Database article, we learned how to integrate Room Database to Android applications and perform CRUD operations.
In this article, we will learn Room Database something more in detail.
If we have to ignore any column from the Entity then you can use @Ignore annotation
1 2 |
@Ignore private long updatedDate; |
or you can use the ignoredColumns attribute in Entity to ignore columns.
1 |
@Entity(tableName = "table_user", ignoredColumns = {"updatedDate"}) |
If we have to add any existing Entity or POJO/Model class to Entity class then we can use @Embedded annotation.
1 2 |
@Embedded public PojoClass pojo; |
To alter any Entity in Room Database then we have to follow the below steps:
1 |
@Database(entities = {User.class}, version = 2) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Migration rules static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { database.execSQL("CREATE TABLE `User` (`id` INTEGER, " + "`name` TEXT, PRIMARY KEY(`id`))"); } }; //adding migration rules to Room Builder Room.databaseBuilder(getApplicationContext(), MyDatabase.class, "my_database") .addMigrations(MIGRATION_1_2) .build(); |
1 2 3 4 |
Room.databaseBuilder(getApplicationContext(), MyDatabase.class, "my_database") .fallbackToDestructiveMigration()//<-- .build(); |
The room will auto-create Impl class during compile time for every @Dao and it will look like below. Here if you see how it’s auto-creating queries for Create, Insert, Delete, and Update and also using Cursors to return data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
package com.androhub.roomdatabasedemo; import android.database.Cursor; import androidx.room.EntityDeletionOrUpdateAdapter; import androidx.room.EntityInsertionAdapter; import androidx.room.RoomDatabase; import androidx.room.RoomSQLiteQuery; import androidx.room.util.CursorUtil; import androidx.room.util.DBUtil; import androidx.sqlite.db.SupportSQLiteStatement; import java.lang.Override; import java.lang.String; import java.lang.SuppressWarnings; import java.util.ArrayList; import java.util.List; @SuppressWarnings({"unchecked", "deprecation"}) public final class UserDao_Impl implements UserDao { private final RoomDatabase __db; private final EntityInsertionAdapter<User> __insertionAdapterOfUser; private final EntityInsertionAdapter<User> __insertionAdapterOfUser_1; private final EntityDeletionOrUpdateAdapter<User> __deletionAdapterOfUser; private final EntityDeletionOrUpdateAdapter<User> __updateAdapterOfUser; public UserDao_Impl(RoomDatabase __db) { this.__db = __db; this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) { @Override public String createQuery() { return "INSERT OR REPLACE INTO `table_user` (`row_id`,`name`,`email`,`phone_number`,`createdDate`) VALUES (nullif(?, 0),?,?,?,?)"; } @Override public void bind(SupportSQLiteStatement stmt, User value) { stmt.bindLong(1, value.getId()); if (value.getName() == null) { stmt.bindNull(2); } else { stmt.bindString(2, value.getName()); } if (value.getEmail() == null) { stmt.bindNull(3); } else { stmt.bindString(3, value.getEmail()); } if (value.getNumber() == null) { stmt.bindNull(4); } else { stmt.bindString(4, value.getNumber()); } stmt.bindLong(5, value.createdDate); } }; this.__insertionAdapterOfUser_1 = new EntityInsertionAdapter<User>(__db) { @Override public String createQuery() { return "INSERT OR ABORT INTO `table_user` (`row_id`,`name`,`email`,`phone_number`,`createdDate`) VALUES (nullif(?, 0),?,?,?,?)"; } @Override public void bind(SupportSQLiteStatement stmt, User value) { stmt.bindLong(1, value.getId()); if (value.getName() == null) { stmt.bindNull(2); } else { stmt.bindString(2, value.getName()); } if (value.getEmail() == null) { stmt.bindNull(3); } else { stmt.bindString(3, value.getEmail()); } if (value.getNumber() == null) { stmt.bindNull(4); } else { stmt.bindString(4, value.getNumber()); } stmt.bindLong(5, value.createdDate); } }; this.__deletionAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) { @Override public String createQuery() { return "DELETE FROM `table_user` WHERE `row_id` = ?"; } @Override public void bind(SupportSQLiteStatement stmt, User value) { stmt.bindLong(1, value.getId()); } }; this.__updateAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) { @Override public String createQuery() { return "UPDATE OR ABORT `table_user` SET `row_id` = ?,`name` = ?,`email` = ?,`phone_number` = ?,`createdDate` = ? WHERE `row_id` = ?"; } @Override public void bind(SupportSQLiteStatement stmt, User value) { stmt.bindLong(1, value.getId()); if (value.getName() == null) { stmt.bindNull(2); } else { stmt.bindString(2, value.getName()); } if (value.getEmail() == null) { stmt.bindNull(3); } else { stmt.bindString(3, value.getEmail()); } if (value.getNumber() == null) { stmt.bindNull(4); } else { stmt.bindString(4, value.getNumber()); } stmt.bindLong(5, value.createdDate); stmt.bindLong(6, value.getId()); } }; } @Override public long insert(final User t) { __db.assertNotSuspendingTransaction(); __db.beginTransaction(); try { long _result = __insertionAdapterOfUser.insertAndReturnId(t); __db.setTransactionSuccessful(); return _result; } finally { __db.endTransaction(); } } @Override public long[] insert(final User... t) { __db.assertNotSuspendingTransaction(); __db.beginTransaction(); try { long[] _result = __insertionAdapterOfUser_1.insertAndReturnIdsArray(t); __db.setTransactionSuccessful(); return _result; } finally { __db.endTransaction(); } } @Override public long[] insert(final List<User> tList) { __db.assertNotSuspendingTransaction(); __db.beginTransaction(); try { long[] _result = __insertionAdapterOfUser_1.insertAndReturnIdsArray(tList); __db.setTransactionSuccessful(); return _result; } finally { __db.endTransaction(); } } @Override public int delete(final User t) { __db.assertNotSuspendingTransaction(); int _total = 0; __db.beginTransaction(); try { _total +=__deletionAdapterOfUser.handle(t); __db.setTransactionSuccessful(); return _total; } finally { __db.endTransaction(); } } @Override public int update(final User t) { __db.assertNotSuspendingTransaction(); int _total = 0; __db.beginTransaction(); try { _total +=__updateAdapterOfUser.handle(t); __db.setTransactionSuccessful(); return _total; } finally { __db.endTransaction(); } } @Override public List<User> getAllUsers() { final String _sql = "select * from table_user"; final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0); __db.assertNotSuspendingTransaction(); final Cursor _cursor = DBUtil.query(__db, _statement, false, null); try { final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "row_id"); final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name"); final int _cursorIndexOfEmail = CursorUtil.getColumnIndexOrThrow(_cursor, "email"); final int _cursorIndexOfNumber = CursorUtil.getColumnIndexOrThrow(_cursor, "phone_number"); final int _cursorIndexOfCreatedDate = CursorUtil.getColumnIndexOrThrow(_cursor, "createdDate"); final List<User> _result = new ArrayList<User>(_cursor.getCount()); while(_cursor.moveToNext()) { final User _item; _item = new User(); final int _tmpId; _tmpId = _cursor.getInt(_cursorIndexOfId); _item.setId(_tmpId); final String _tmpName; _tmpName = _cursor.getString(_cursorIndexOfName); _item.setName(_tmpName); final String _tmpEmail; _tmpEmail = _cursor.getString(_cursorIndexOfEmail); _item.setEmail(_tmpEmail); final String _tmpNumber; _tmpNumber = _cursor.getString(_cursorIndexOfNumber); _item.setNumber(_tmpNumber); _item.createdDate = _cursor.getLong(_cursorIndexOfCreatedDate); _result.add(_item); } return _result; } finally { _cursor.close(); _statement.release(); } } } |
If we have to insert, delete, or update multiple data at a time then we can use the below code. The below methods are taking array[] of User but we can use List as well.
1 2 3 4 5 6 7 8 |
@Insert long[] insert(User... user); @Delete void delete(User... user); @Update void update(User... user); |
If we work on the bigger project then we see for all Entities we have some queries which are common everywhere. So to remove the duplication we can create a Generic BaseDao and it can be extended by other Dao’s.
You can add other common methods as well depending upon the redundancy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Update; import java.util.List; public interface BaseDao<T> { @Insert(onConflict = OnConflictStrategy.REPLACE) long insert(T t); @Insert long[] insert(T... t); @Insert long[] insert(List<T> tList); @Delete int delete(T t); @Update int update(T t); } |
If we have to write the query which will take some field as input and on that basis it should return the data then we can use something like below:
1 2 |
@Query("select * from table_user where name= :query") List<User> getAllUsers(String query); |
Let’s suppose we have to debug our database means checking that the values are properly inserting or not and what is the schema of the Database. There are two ways we can do this:
1 |
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' |
Once you are done with syncing run your app and you will see the local URL in your logs. Click on the URL and it will open the browser where you can see your database and preferences.
Note: Your device and system both should be on the same wifi network else you will get URL as 0.0.0.0.
If you have a rooted device or you are running your app in Emulator then you can directly access the database from your internal storage but from there you cannot modify or do any changes which can affect your app database.
You can find all the additional annotations discussed above in the following download link.
Thanks.
Subscribe to us and get the latest news.