Incrementally migrate from SQLite to Room

Florina Muntenescu
Dec 19, 2017 · 5 min read


Project setup

First PR

Create the entity classes

+ @Entity(tableName = "users")
public class User {

+ @PrimaryKey
+ @ColumnInfo(name = "userid")
private int mId;

+ @ColumnInfo(name = "username")
private String mUserName;

public User(int id, String userName) {
this.mId = id;
this.mUserName = userName;

public int getId() { return mId; }

public String getUserName() { return mUserName; }

Create the Room database

@Database(entities = {<all entity classes>}, 
version = <incremented_sqlite_version>)
public abstract class AppDatabase extends RoomDatabase {
private static UsersDatabase INSTANCE; static final Migration MIGRATION_<sqlite_version>_<incremented_sqlite_version>
= new Migration(<sqlite_version>, <incremented_sqlite_version>) {
@Override public void migrate(
SupportSQLiteDatabase database) {
// Since we didn’t alter the table, there’s nothing else
// to do here.

Update the class that works with SQLiteOpenHelper

public class LocalUserDataSource {
private SupportSQLiteOpenHelper mDbHelper;
LocalUserDataSource(@NonNull SupportSQLiteOpenHelper helper) {
mDbHelper = helper;
SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
public void insertOrUpdateUser(User user) {
SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();

ContentValues values = new ContentValues();
values.put(COLUMN_NAME_ENTRY_ID, user.getId());
values.put(COLUMN_NAME_USERNAME, user.getUserName());

- db.insertWithOnConflict(TABLE_NAME, null, values,
+ db.insert(TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE,
+ values);
Cursor query(String query);
Cursor query(String query, Object[] bindArgs);
Cursor query(SupportSQLiteQuery query);
Cursor query(SupportSQLiteQuery query, CancellationSignal cancellationSignal);
public User getFirstUserAlphabetically() {
User user = null;
SupportSQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projection = {

// Get the first user from the table ordered alphabetically
- Cursor cursor = db.query(TABLE_NAME, projection, null,
- null, null, null, COLUMN_NAME_USERNAME + “ ASC “, “1”);

+ SupportSQLiteQuery query =
+ SupportSQLiteQueryBuilder.builder(TABLE_NAME)
+ .columns(projection)
+ .limit(“1”)
+ .create();

+ Cursor cursor = db.query(query);

if (c !=null && c.getCount() > 0){
// read data from cursor
if (c !=null){
return user;

Following PRs

public interface UserDao {
User getFirstUserAlphabetically();
public class LocalDataSource {     private UserDao mUserDao;     public User getFirstUserAlphabetically() {
return mUserDao.getFirstUserAlphabetically();

Android Developers

The official Android Developers publication on Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store