Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Migrating Existing SQLite Applications to Room ...

Migrating Existing SQLite Applications to Room Persistence Library - by Caglar Yuce Kaya

This topic was presented at the Mobile Developer Meetup Braunschweig October (https://www.meetup.com/de-DE/GDG-Braunschweig/events/244090003/) by by Caglar Yuce Kaya

Avatar for GDG Braunschweig

GDG Braunschweig

October 25, 2017

Other Decks in Programming

Transcript

  1. What is Room Persistence Library? • An abstraction layer over

    SQLite -> Compile-time verification of raw SQL queries -> No boilerplate code • Release Candidate
  2. Gradle Dependencies • Main build.gradle file: • app/build.gradle: allprojects {

    repositories { ... maven { url 'https://maven.google.com' } } } dependencies { ... compile "android.arch.persistence.room:runtime:1.0.0-rc1" annotationProcessor "android.arch.persistence.room:compiler:1.0.0-rc1" ... }
  3. Entities @Entity(tableName = "users") public class User { @PrimaryKey private

    String mId; private String mUserName; @ColumnInfo(name = "last_update") private Date mDate; @Ignore private int age; @Ignore public User(String userName) { ... } public User(String id, String userName, Date date) { ... } ... }
  4. Data Access Objects @Dao public interface UserDao { @Query("SELECT *

    FROM users") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Update void update(User... users); @Delete void delete(User user); @Query ("DELETE FROM users") void deleteAll(); }
  5. Database @Database(entities = {User.class}, version = 4) public abstract class

    AppDatabase extends RoomDatabase { public abstract UserDao userDao(); private static AppDatabase INSTANCE; public static AppDatabase getDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "example_db") .allowMainThreadQueries() .addMigrations(MIGRATION_1_4, MIGRATION_2_4, MIGRATION_3_4) .build(); } return INSTANCE; } ... }
  6. Database static final Migration MIGRATION_1_4 = new Migration(1, 4) {

    @Override public void migrate(SupportSQLiteDatabase database) { ... } }; static final Migration MIGRATION_2_4 = new Migration(2, 4) { @Override public void migrate(SupportSQLiteDatabase database) { ... } }; static final Migration MIGRATION_3_4 = new Migration(3, 4) { @Override public void migrate(SupportSQLiteDatabase database) { ... } };
  7. Type Converters public class DateTimestampConverter { @TypeConverter public static Date

    fromTimestamp(Long value) { return value == null ? null : new Date(value); } @TypeConverter public static Long dateToTimestamp(Date date) { return date == null ? null : date.getTime(); } }
  8. Type Converters @Entity(tableName = "users") public class User { ...

    @ColumnInfo (name = "last_update") @TypeConverters(DateTimeStampConverter.class) private Date mDate; ... } @Entity(tableName = "users") @TypeConverters(DateTimeStampConverter.class) public class User { ... @ColumnInfo (name = "last_update") private Date mDate; ... }
  9. Type Converters @Dao public interface UserDao { ... @Query("SELECT last_update

    FROM users WHERE uid IN (:userIds)") @TypeConverters(DateTimeStampConverter.class) List<Date> getLastUpdates(int[] userIds); ... } @Dao @TypeConverters(DateTimeStampConverter.class) public interface UserDao { ... }
  10. Encountered Problems • float/boolean types are not allowed • New

    and old databases must be identical • SQLite doesn’t allow to alter column type -> Recreate the table at migration
  11. Encountered Problems • Object types are nullable by default, but

    they can be made NOT NULL • Primitive types are NOT NULL by default, and they can’t be made nullable. @Entity(tableName = "users") public class User { ... @ColumnInfo (name = "last_update") @TypeConverters(DateTimeStampConverter.class) @Nonnull private Date mDate; ... }
  12. Encountered Problems • Migration Errors Caused by: java.lang.IllegalStateException: Migration didn't

    properly handle xxx. Expected: TableInfo{name='name', columns={col1=Column{name='col1', type='TEXT', notNull=false, primaryKeyPosition=0}, ....}, foreignKeys=[]} Found: TableInfo{name='name', columns={col1=Column{name='col1', type='INTEGER', notNull=false, primaryKeyPosition=0}, ....}, foreignKeys=[]}