SlideShare a Scribd company logo
@magdamiu
Room: an SQLite object
mapping library
Magda Miu
Mobile Tech Lead @Roweb
magdamiu.com
@magdamiu
@magdamiu
/magdamiu
If you would have the
possibility to change
something in the Android
development what will it be
that thing?
I don’t want to deal
with technical things.
I just want
to deliver the project.
yiğit boyar - Architecture Components
– Behind the Scenes
I don’t want to deal
with technical things.
I just want
to deliver the project.
yiğit boyar - Architecture Components
– Behind the Scenes
public class DatabaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "CountriesManager";
// Countries table name
private static final String TABLE_Countries = "Country";
// Countries Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_TOWN = "town";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_Countries_TABLE = "CREATE TABLE " + TABLE_Countries + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_TOWN + " TEXT" + ")";
db.execSQL(CREATE_Countries_TABLE);
}
public void addCountry(Country country) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(KEY_NAME, country.getName()); // Country Name
values.put(KEY_TOWN, country.getTown()); // Country Town
db.insert(TABLE_Countries, null, values);
db.setTransactionSuccessful();
} catch (Exception e) {
Log.d(TAG, "Error while trying to add country to database");
} finally {
db.endTransaction();
}
}
Country getCountry(int id) {
SQLiteDatabase db = this.getReadableDatabase(); Country country = null;
Cursor cursor = db.query(TABLE_Countries, new String[]{KEY_ID,
KEY_NAME, KEY_TOWN}, KEY_ID + "=?",
new String[]{String.valueOf(id)}, null, null, null, null);
try {
if (cursor != null) {
cursor.moveToFirst();
country = new Country(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2));
}
} catch (Exception e) {
Log.d(TAG, "Error while trying to get countries from database");
} finally {
if (cursor != null && !cursor.isClosed()) cursor.close();
SQLite
Challenges
Boilerplate code
SQLite
Challenges
Boilerplate code
SQL queries checked at runtime
SQLite
Challenges
Boilerplate code
SQL queries checked at runtime
Db operations on the main thread
SQLite
Challenges
Boilerplate code
SQL queries checked at runtime
Db operations on the main thread
Unmaintainable code
SQLite
Challenges
Boilerplate code
SQL queries checked at runtime
Db operations on the main thread
Unmaintainable code
Untestable code
Navigation
LiveData
Room
ViewModel
Lifecycle
Pagination
Work
Manager
Architecture Components
ROOM an SQLite object mapping library
Why
ORM?
Productivity
Why
ORM?
Productivity
Application Design
Why
ORM?
Productivity
Application Design
Application Maintainability
YES NO
Compile time
query verification
x
Migration support x
Java Query Builder
API
x
SQL Completion in
Android Studio
x
Relationships x
Architecture Components - Behind the Scenes by Yiğit Boyar
Dependencies 1.1.1. Room dependency
2.0.0 AndroidX
01 Entity
Components
01 Entity
Dao02
Components
01 Entity
Dao02
Database03
Components
01 Entity
public class Company {
private int companyId;
private String name;
Bitmap picture;
}
public class Company {
private int companyId;
private String name;
Bitmap picture;
}
Company
id integer
name text
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
@ColumnInfo(name = "name")
private String name;
@Ignore
Bitmap picture;
Company
id integer
name text
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
@ColumnInfo(name = "name")
private String name;
@Ignore
Bitmap picture;
Company
id integer
name text
Company
id integer
name text
Company
id integer
name text
date_added
Company
id integer
name text
date_added date
Company
id integer
name text
date_added date
Company
id integer
name text
date_added
Company
id integer
name text
date_added integer
Company
id integer
name text
date_added integer
@TypeConverter Converts your custom object type into a known
type in terms of database types.
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
Company
id integer
name text
date integer
@ColumnInfo(name = "date_updated")
@TypeConverters(DateConverter.class)
private Date itemUpdatedDate;
-------------------------------------------------
@ColumnInfo(name = "date_updated")
@TypeConverters(DateConverter.class)
private Date itemUpdatedDate;
-------------------------------------------------
@Dao
@TypeConverters(DateConverter.class)
public interface CompanyDao
-------------------------------------------------
@ColumnInfo(name = "date_updated")
@TypeConverters(DateConverter.class)
private Date itemUpdatedDate;
-------------------------------------------------
@Dao
@TypeConverters(DateConverter.class)
public interface CompanyDao
-------------------------------------------------
@Database(entities = {Company.class}, version = 1)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase
Dao02
@Dao
public interface CompanyDao {
@Query("SELECT * FROM Company")
LiveData<List<Company>> getAllCountries();
@Insert
void insertCompany(Company company);
@Update
void updateCompany(Company company);
@Delete
void deleteCompany(Company company);
}
@Dao
public interface CompanyDao {
@Query("SELECT * FROM Company")
List<Company> getAllCompanies();
@Insert
void insertCompany(Company company);
@Update
void updateCompany(Company company);
@Delete
void deleteCompany(Company company);
}
@Dao
public interface CompanyDao {
@Query("SELECT * FROM Companies")
List<Company> getAllCompanies();
@Insert
void insertCompany(Company company);
@Update
void updateCompany(Company company);
@Delete
void deleteCompany(Company company);
}
@Dao
public interface CompanyDao {
@Query("SELECT * FROM Companies")
List<Company> getAllCompanies();
@Insert
void insertCompany(Company company);
@Update
void updateCompany(Company company);
@Delete
void deleteCompany(Company company);
}
@Dao
public interface DepartmentDao {
@Insert
void insertAll(List<Department> departments);
}
public class DepartmentDao_Impl implements DepartmentDao {
Behind the scenes
public class DepartmentDao_Impl implements DepartmentDao {
private final RoomDatabase __db;
Behind the scenes
public class DepartmentDao_Impl implements DepartmentDao {
private final RoomDatabase __db;
public void insertAll(List<Department> departments) {
this.__db.beginTransaction();
try {
this.__insertionAdapterOfDepartment.insert(departments);
this.__db.setTransactionSuccessful();
} finally {
this.__db.endTransaction();
}
}
}
Behind the scenes
Database02
@Database(entities = {Company.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CompanyDao companyDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.build();
}
return INSTANCE;
@Database(entities = {Company.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CompanyDao companyDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.build();
}
return INSTANCE;
@Database(entities = {Company.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CompanyDao companyDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.build();
}
return INSTANCE;
@Database(entities = {Company.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CompanyDao companyDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.build();
}
return INSTANCE;
@Database(entities = {Company.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract CompanyDao companyDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.build();
}
return INSTANCE;
“Relations”
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
private int directorId;
private Employee director;
public Employee getDirector() {
if(director == null) {
director = getEmployee(employeeId)
}
return director;
}
@Query("SELECT * FROM Company")
List<Company> getAllCompanies();
@Query("SELECT * FROM Company")
List<Company> getAllCompanies();
txtName.setText(company.getDirector().getName());
@Query("SELECT * FROM Company")
List<Company> getAllCompanies();
txtName.setText(company.getDirector().getName());
HQ office
Krakow
public class Location {
private double latitude;
private double longitude;
// getters
// setters
@Embedded Nested objects
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "date_updated")
@TypeConverters(DateConverter.class)
private Date itemUpdatedDate;
@Embedded
private Location location;
@Embedded
private Location headLocation;
@Entity(tableName = "Company")
public class Company {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int companyId;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "date_updated")
@TypeConverters(DateConverter.class)
private Date itemUpdatedDate;
@Embedded
private Location location;
@Embedded(prefix = "hq_")
private Location headLocation;
Company
id integer
name text
date integer
latitude real
longitude real
hq_latitude real
hq_longitude real
Employee
id integer
name text
Employee
id integer
name text
company_id integer
Employee
id integer
name text
company_id integer
Company
id integer
name text
date integer
latitude real
longitude real
hq_latitude real
hq_longitude real
1 M
@ForeignKey constraints across Entities that will ensure that
the relationship is valid on database changes
@Entity(foreignKeys = @ForeignKey(entity = Company.class,
parentColumns = "id",
childColumns = "company_id",
onDelete = ForeignKey.NO_ACTION))
public class Employee {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int employeeId;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "company_id")
private int companyId;
@Relation A convenience annotation which can be used in a
Pojo to automatically fetch relation entities
@Entity
public class Department {
@PrimaryKey
private int id;
private int companyId;
private String name;
…
Department
id integer
name text
public class CompanyAndAllDepartments {
@Embedded
public Company company;
@Relation(parentColumn = "id", entityColumn = "companyId", entity = Department.class)
public List<Department> departments;
…
---------------------------------------------------------------------------------
public class CompanyAndAllDepartments {
@Embedded
public Company company;
@Relation(parentColumn = "id", entityColumn = "companyId", entity = Department.class)
public List<Department> departments;
…
@Dao
public interface CompanyDepartmentsDao {
@Transaction
@Query("SELECT * FROM Company WHERE id = :companyId")
CompanyAndAllDepartments loadCompanyAllDepartments(long companyId);
…
---------------------------------------------------------------------------------
Queries
@
Insert
@
Update
@
Delete
@
Q
uery
@Insert
@Update
@Delete
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertCompany(Company company);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Company> companies);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Company... companies);
------------------------------------------------
@Insert
@Update
@Delete
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertCompany(Company company);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Company> companies);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Company... companies);
@Update
void updateCompany(Company company);
@Update
void updateCompanies(Company... company);
------------------------------------------------
------------------------------------------------
@Insert
@Update
@Delete
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertCompany(Company company);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Company> companies);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Company... companies);
@Update
void updateCompany(Company company);
@Update
void updateCompanies(Company... company);
------------------------------------------------
@Delete
void deleteCompany(Company company);
@Delete
void deleteCompanies(Company... company);
------------------------------------------------
@Query*
@Query("SELECT * FROM Company WHERE name =
:companyName")
List<Company> getCompanies(String companyName);
@Query("SELECT * FROM Company")
LiveData<List<Company>> getAllCompanies();
@Query("SELECT * FROM Company")
Flowable<List<Company>> getAllCompanies();
@RawQuery(observedEntities = Employee.class)
LiveData<List<Employee>>
getAllEmployeesWithLimit(SupportSQLiteQuery query);
java.lang.IllegalStateException: Cannot access database
on the main thread since it may potentially lock the UI
for a long period of time.
@Transaction
@Dao
public abstract class DepartmentDao {
@Insert
public abstract void insert(Department product);
@Delete
public abstract void delete(Department product);
@Transaction
public void insertAndDeleteInTransaction(Department
newDepartment, Department oldDepartment) {
// Anything inside this method runs in a single
transaction.
insert(newDepartment);
delete(oldDepartment);
}
}
Threading - Room 1.0
First thread Second Thread
Threading - Room 1.0
First thread Second Thread
WRITE
Threading - Room 1.0
First thread Second Thread
WRITE WAITING...
Threading - Room 1.0
First thread Second Thread
WRITE WAITING...
READ
Threading - Room 1.1
First thread Second Thread
Threading - Room 1.1
First thread Second Thread
WRITE READ
Migration
Company
id integer
name text
date integer
latitude real
longitude real
hq_latitude real
hq_longitude real
Version 1
Company
id integer
name text
date integer
latitude real
longitude real
hq_latitude real
hq_longitude real
ref_no text
Version 2
Migration
Version yVersion x
Migration
Version yVersion x
------------------------------------------------------------
Migration
Version yVersion x
Version 2Version 1
------------------------------------------------------------
Migration
// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// oldVersion -> newVersion
}
// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// oldVersion -> newVersion
}
“CLASSICAL”
APPRO
ACH
final Migration MIGRATION_X_Y = new Migration(X, Y) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// your code here
}
};
final Migration MIGRATION_X_Y = new Migration(X, Y) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// your code here
}
};
RO
O
M
APPRO
ACH
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Company "
+ " ADD COLUMN ref_no TEXT");
}
};
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
DATABASE_NAME)
.addMigrations(MIGRATION_1_2)
.build();
}
return INSTANCE;
}
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
DATABASE_NAME)
.addMigrations(MIGRATION_1_2)
.build();
}
return INSTANCE;
}
Version 2Version 1
room_master_table
id identity_hash
42 <v1_hash>
room_master_table
id identity_hash
42 <v2_hash>
Migration
/**
* You can set annotation processor argument (room.schemaLocation) to tell Room to
* export the schema into a folder. Even though it is not mandatory, it is a good
* practice to have version history in your codebase and you should commit that file
* into your version control system (but don't ship it with your app!).
* */
//export schema
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
/**
* Room will throw an IllegalStateException if you don’t provide a Migration.
* */
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.fallbackToDestructiveMigration()
.build();
}
/**
* Room will throw an IllegalStateException if you don’t provide a Migration.
* */
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.fallbackToDestructiveMigration()
.build();
}
/**
* Room will throw an IllegalStateException if you don’t provide a Migration.
* */
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class,
"company-db")
.fallbackToDestructiveMigrationFrom(int...
startVersions)
.build();
}
Room
Advantages
Less boilerplate code
SQL queries checked at compile time
No db operations on the main thread
Maintainable code
Migration support
Questions
● Official docs:
https://developer.android.com/topic/libraries/archite
cture/room.html
● Google code samples and Youtube channel:
https://github.com/googlesamples/android-architec
ture-components
● CommonsWare:
https://commonsware.com/AndroidArch/
● Slides from: https://www.slidescarnival.com/ and gifs
from: https://gifer.com
Resources
Connecting designers
and developers!
Dziękuję!
Thank you!

More Related Content

What's hot

Hibernate Developer Reference
Hibernate Developer ReferenceHibernate Developer Reference
Hibernate Developer Reference
Muthuselvam RS
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
Christoffer Noring
 
Hibernate
HibernateHibernate
Hibernate
Prashant Kalkar
 
Extensible Data Modeling
Extensible Data ModelingExtensible Data Modeling
Extensible Data Modeling
Karwin Software Solutions LLC
 
React & Redux for noobs
React & Redux for noobsReact & Redux for noobs
React & Redux for noobs
[T]echdencias
 
Java EE and Glassfish
Java EE and GlassfishJava EE and Glassfish
Java EE and Glassfish
Carol McDonald
 
Hibernate inheritance and relational mappings with examples
Hibernate inheritance and relational mappings with examplesHibernate inheritance and relational mappings with examples
Hibernate inheritance and relational mappings with examples
Er. Gaurav Kumar
 
Modern android development
Modern android developmentModern android development
Modern android development
Khiem-Kim Ho Xuan
 
Data Migrations in the App Engine Datastore
Data Migrations in the App Engine DatastoreData Migrations in the App Engine Datastore
Data Migrations in the App Engine Datastore
Ryan Morlok
 
Android DevConference - Android Clean Architecture
Android DevConference - Android Clean ArchitectureAndroid DevConference - Android Clean Architecture
Android DevConference - Android Clean Architecture
iMasters
 
Jdbc
JdbcJdbc
Hibernate in Action
Hibernate in ActionHibernate in Action
Hibernate in Action
Akshay Ballarpure
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
Samnang Chhun
 
Hibernate in Nutshell
Hibernate in NutshellHibernate in Nutshell
Hibernate in Nutshell
Onkar Deshpande
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
Hendrik Ebbers
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batis
day
 
WOdka
WOdkaWOdka
Dao example
Dao exampleDao example
Dao example
myrajendra
 
Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2
Christoffer Noring
 
Struts N E W
Struts N E WStruts N E W
Struts N E W
patinijava
 

What's hot (20)

Hibernate Developer Reference
Hibernate Developer ReferenceHibernate Developer Reference
Hibernate Developer Reference
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
 
Hibernate
HibernateHibernate
Hibernate
 
Extensible Data Modeling
Extensible Data ModelingExtensible Data Modeling
Extensible Data Modeling
 
React & Redux for noobs
React & Redux for noobsReact & Redux for noobs
React & Redux for noobs
 
Java EE and Glassfish
Java EE and GlassfishJava EE and Glassfish
Java EE and Glassfish
 
Hibernate inheritance and relational mappings with examples
Hibernate inheritance and relational mappings with examplesHibernate inheritance and relational mappings with examples
Hibernate inheritance and relational mappings with examples
 
Modern android development
Modern android developmentModern android development
Modern android development
 
Data Migrations in the App Engine Datastore
Data Migrations in the App Engine DatastoreData Migrations in the App Engine Datastore
Data Migrations in the App Engine Datastore
 
Android DevConference - Android Clean Architecture
Android DevConference - Android Clean ArchitectureAndroid DevConference - Android Clean Architecture
Android DevConference - Android Clean Architecture
 
Jdbc
JdbcJdbc
Jdbc
 
Hibernate in Action
Hibernate in ActionHibernate in Action
Hibernate in Action
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
 
Hibernate in Nutshell
Hibernate in NutshellHibernate in Nutshell
Hibernate in Nutshell
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batis
 
WOdka
WOdkaWOdka
WOdka
 
Dao example
Dao exampleDao example
Dao example
 
Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2
 
Struts N E W
Struts N E WStruts N E W
Struts N E W
 

Similar to MobiConf 2018 | Room: an SQLite object mapping library

From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
Jose Manuel Pereira Garcia
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
Ahmad Arif Faizin
 
Android Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, VonageAndroid Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, Vonage
DroidConTLV
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
Hassan Abid
 
Cleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsCleaning your architecture with android architecture components
Cleaning your architecture with android architecture components
Debora Gomez Bertoli
 
Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2
Max Pronko
 
Demystifying The Solid Works Api
Demystifying The Solid Works ApiDemystifying The Solid Works Api
Demystifying The Solid Works Api
Razorleaf Corporation
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
toddbr
 
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Peter Martin
 
Android Architecture Components with Kotlin
Android Architecture Components with KotlinAndroid Architecture Components with Kotlin
Android Architecture Components with Kotlin
Adit Lal
 
SOLID & IoC Principles
SOLID & IoC PrinciplesSOLID & IoC Principles
SOLID & IoC Principles
Pavlo Hodysh
 
Intake 38 data access 5
Intake 38 data access 5Intake 38 data access 5
Intake 38 data access 5
Mahmoud Ouf
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
Anton Novikau
 
NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020
Thodoris Bais
 
Cloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan GasimovCloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan Gasimov
GlobalLogic Ukraine
 
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
Mark Rackley
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
DataArt
 
IOC + Javascript
IOC + JavascriptIOC + Javascript
IOC + Javascript
Brian Cavalier
 
Green dao
Green daoGreen dao
Green dao
Droidcon Berlin
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
Christian Panadero
 

Similar to MobiConf 2018 | Room: an SQLite object mapping library (20)

From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
 
Android Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, VonageAndroid Architecture Components - Guy Bar on, Vonage
Android Architecture Components - Guy Bar on, Vonage
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Cleaning your architecture with android architecture components
Cleaning your architecture with android architecture componentsCleaning your architecture with android architecture components
Cleaning your architecture with android architecture components
 
Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2
 
Demystifying The Solid Works Api
Demystifying The Solid Works ApiDemystifying The Solid Works Api
Demystifying The Solid Works Api
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
 
Android Architecture Components with Kotlin
Android Architecture Components with KotlinAndroid Architecture Components with Kotlin
Android Architecture Components with Kotlin
 
SOLID & IoC Principles
SOLID & IoC PrinciplesSOLID & IoC Principles
SOLID & IoC Principles
 
Intake 38 data access 5
Intake 38 data access 5Intake 38 data access 5
Intake 38 data access 5
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 
NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020
 
Cloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan GasimovCloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan Gasimov
 
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
#SPSEMEA SharePoint & jQuery - What I wish I would have known a year ago..
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
 
IOC + Javascript
IOC + JavascriptIOC + Javascript
IOC + Javascript
 
Green dao
Green daoGreen dao
Green dao
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 

Recently uploaded

Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
panagenda
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 

Recently uploaded (20)

Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 

MobiConf 2018 | Room: an SQLite object mapping library

  • 1. @magdamiu Room: an SQLite object mapping library
  • 2. Magda Miu Mobile Tech Lead @Roweb magdamiu.com @magdamiu @magdamiu /magdamiu
  • 3. If you would have the possibility to change something in the Android development what will it be that thing?
  • 4. I don’t want to deal with technical things. I just want to deliver the project. yiğit boyar - Architecture Components – Behind the Scenes
  • 5.
  • 6. I don’t want to deal with technical things. I just want to deliver the project. yiğit boyar - Architecture Components – Behind the Scenes
  • 7.
  • 8. public class DatabaseHandler extends SQLiteOpenHelper { // All Static variables // Database Version private static final int DATABASE_VERSION = 1; // Database Name private static final String DATABASE_NAME = "CountriesManager"; // Countries table name private static final String TABLE_Countries = "Country"; // Countries Table Columns names private static final String KEY_ID = "id"; private static final String KEY_NAME = "name"; private static final String KEY_TOWN = "town";
  • 9. public DatabaseHandler(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } // Creating Tables @Override public void onCreate(SQLiteDatabase db) { String CREATE_Countries_TABLE = "CREATE TABLE " + TABLE_Countries + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," + KEY_TOWN + " TEXT" + ")"; db.execSQL(CREATE_Countries_TABLE); }
  • 10. public void addCountry(Country country) { SQLiteDatabase db = this.getWritableDatabase(); db.beginTransaction(); try { ContentValues values = new ContentValues(); values.put(KEY_NAME, country.getName()); // Country Name values.put(KEY_TOWN, country.getTown()); // Country Town db.insert(TABLE_Countries, null, values); db.setTransactionSuccessful(); } catch (Exception e) { Log.d(TAG, "Error while trying to add country to database"); } finally { db.endTransaction(); } }
  • 11. Country getCountry(int id) { SQLiteDatabase db = this.getReadableDatabase(); Country country = null; Cursor cursor = db.query(TABLE_Countries, new String[]{KEY_ID, KEY_NAME, KEY_TOWN}, KEY_ID + "=?", new String[]{String.valueOf(id)}, null, null, null, null); try { if (cursor != null) { cursor.moveToFirst(); country = new Country(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2)); } } catch (Exception e) { Log.d(TAG, "Error while trying to get countries from database"); } finally { if (cursor != null && !cursor.isClosed()) cursor.close();
  • 12.
  • 15. SQLite Challenges Boilerplate code SQL queries checked at runtime Db operations on the main thread
  • 16. SQLite Challenges Boilerplate code SQL queries checked at runtime Db operations on the main thread Unmaintainable code
  • 17. SQLite Challenges Boilerplate code SQL queries checked at runtime Db operations on the main thread Unmaintainable code Untestable code
  • 19.
  • 20. ROOM an SQLite object mapping library
  • 24. YES NO Compile time query verification x Migration support x Java Query Builder API x SQL Completion in Android Studio x Relationships x Architecture Components - Behind the Scenes by Yiğit Boyar
  • 25.
  • 26. Dependencies 1.1.1. Room dependency 2.0.0 AndroidX
  • 31. public class Company { private int companyId; private String name; Bitmap picture; }
  • 32. public class Company { private int companyId; private String name; Bitmap picture; } Company id integer name text
  • 33. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId; @ColumnInfo(name = "name") private String name; @Ignore Bitmap picture; Company id integer name text
  • 34. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId; @ColumnInfo(name = "name") private String name; @Ignore Bitmap picture; Company id integer name text
  • 42. @TypeConverter Converts your custom object type into a known type in terms of database types.
  • 43. public class DateConverter { @TypeConverter public static Date toDate(Long timestamp) { return timestamp == null ? null : new Date(timestamp); } @TypeConverter public static Long toTimestamp(Date date) { return date == null ? null : date.getTime(); } } Company id integer name text date integer
  • 44. @ColumnInfo(name = "date_updated") @TypeConverters(DateConverter.class) private Date itemUpdatedDate; -------------------------------------------------
  • 45. @ColumnInfo(name = "date_updated") @TypeConverters(DateConverter.class) private Date itemUpdatedDate; ------------------------------------------------- @Dao @TypeConverters(DateConverter.class) public interface CompanyDao -------------------------------------------------
  • 46. @ColumnInfo(name = "date_updated") @TypeConverters(DateConverter.class) private Date itemUpdatedDate; ------------------------------------------------- @Dao @TypeConverters(DateConverter.class) public interface CompanyDao ------------------------------------------------- @Database(entities = {Company.class}, version = 1) @TypeConverters(DateConverter.class) public abstract class AppDatabase extends RoomDatabase
  • 47. Dao02
  • 48. @Dao public interface CompanyDao { @Query("SELECT * FROM Company") LiveData<List<Company>> getAllCountries(); @Insert void insertCompany(Company company); @Update void updateCompany(Company company); @Delete void deleteCompany(Company company); }
  • 49. @Dao public interface CompanyDao { @Query("SELECT * FROM Company") List<Company> getAllCompanies(); @Insert void insertCompany(Company company); @Update void updateCompany(Company company); @Delete void deleteCompany(Company company); }
  • 50. @Dao public interface CompanyDao { @Query("SELECT * FROM Companies") List<Company> getAllCompanies(); @Insert void insertCompany(Company company); @Update void updateCompany(Company company); @Delete void deleteCompany(Company company); }
  • 51. @Dao public interface CompanyDao { @Query("SELECT * FROM Companies") List<Company> getAllCompanies(); @Insert void insertCompany(Company company); @Update void updateCompany(Company company); @Delete void deleteCompany(Company company); }
  • 52. @Dao public interface DepartmentDao { @Insert void insertAll(List<Department> departments); }
  • 53. public class DepartmentDao_Impl implements DepartmentDao { Behind the scenes
  • 54. public class DepartmentDao_Impl implements DepartmentDao { private final RoomDatabase __db; Behind the scenes
  • 55. public class DepartmentDao_Impl implements DepartmentDao { private final RoomDatabase __db; public void insertAll(List<Department> departments) { this.__db.beginTransaction(); try { this.__insertionAdapterOfDepartment.insert(departments); this.__db.setTransactionSuccessful(); } finally { this.__db.endTransaction(); } } } Behind the scenes
  • 57. @Database(entities = {Company.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CompanyDao companyDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .build(); } return INSTANCE;
  • 58. @Database(entities = {Company.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CompanyDao companyDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .build(); } return INSTANCE;
  • 59. @Database(entities = {Company.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CompanyDao companyDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .build(); } return INSTANCE;
  • 60. @Database(entities = {Company.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CompanyDao companyDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .build(); } return INSTANCE;
  • 61. @Database(entities = {Company.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase INSTANCE; public abstract CompanyDao companyDao(); public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .build(); } return INSTANCE;
  • 63. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId;
  • 64. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId; private int directorId; private Employee director; public Employee getDirector() { if(director == null) { director = getEmployee(employeeId) } return director; }
  • 65. @Query("SELECT * FROM Company") List<Company> getAllCompanies();
  • 66. @Query("SELECT * FROM Company") List<Company> getAllCompanies(); txtName.setText(company.getDirector().getName());
  • 67. @Query("SELECT * FROM Company") List<Company> getAllCompanies(); txtName.setText(company.getDirector().getName());
  • 68.
  • 69.
  • 71. public class Location { private double latitude; private double longitude; // getters // setters
  • 73. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "date_updated") @TypeConverters(DateConverter.class) private Date itemUpdatedDate; @Embedded private Location location; @Embedded private Location headLocation;
  • 74. @Entity(tableName = "Company") public class Company { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int companyId; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "date_updated") @TypeConverters(DateConverter.class) private Date itemUpdatedDate; @Embedded private Location location; @Embedded(prefix = "hq_") private Location headLocation;
  • 75. Company id integer name text date integer latitude real longitude real hq_latitude real hq_longitude real
  • 78. Employee id integer name text company_id integer Company id integer name text date integer latitude real longitude real hq_latitude real hq_longitude real 1 M
  • 79. @ForeignKey constraints across Entities that will ensure that the relationship is valid on database changes
  • 80. @Entity(foreignKeys = @ForeignKey(entity = Company.class, parentColumns = "id", childColumns = "company_id", onDelete = ForeignKey.NO_ACTION)) public class Employee { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") private int employeeId; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "company_id") private int companyId;
  • 81. @Relation A convenience annotation which can be used in a Pojo to automatically fetch relation entities
  • 82. @Entity public class Department { @PrimaryKey private int id; private int companyId; private String name; … Department id integer name text
  • 83. public class CompanyAndAllDepartments { @Embedded public Company company; @Relation(parentColumn = "id", entityColumn = "companyId", entity = Department.class) public List<Department> departments; … ---------------------------------------------------------------------------------
  • 84. public class CompanyAndAllDepartments { @Embedded public Company company; @Relation(parentColumn = "id", entityColumn = "companyId", entity = Department.class) public List<Department> departments; … @Dao public interface CompanyDepartmentsDao { @Transaction @Query("SELECT * FROM Company WHERE id = :companyId") CompanyAndAllDepartments loadCompanyAllDepartments(long companyId); … ---------------------------------------------------------------------------------
  • 86. @Insert @Update @Delete @Insert(onConflict = OnConflictStrategy.REPLACE) void insertCompany(Company company); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(List<Company> companies); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(Company... companies); ------------------------------------------------
  • 87. @Insert @Update @Delete @Insert(onConflict = OnConflictStrategy.REPLACE) void insertCompany(Company company); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(List<Company> companies); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(Company... companies); @Update void updateCompany(Company company); @Update void updateCompanies(Company... company); ------------------------------------------------ ------------------------------------------------
  • 88. @Insert @Update @Delete @Insert(onConflict = OnConflictStrategy.REPLACE) void insertCompany(Company company); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(List<Company> companies); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(Company... companies); @Update void updateCompany(Company company); @Update void updateCompanies(Company... company); ------------------------------------------------ @Delete void deleteCompany(Company company); @Delete void deleteCompanies(Company... company); ------------------------------------------------
  • 89. @Query* @Query("SELECT * FROM Company WHERE name = :companyName") List<Company> getCompanies(String companyName); @Query("SELECT * FROM Company") LiveData<List<Company>> getAllCompanies(); @Query("SELECT * FROM Company") Flowable<List<Company>> getAllCompanies(); @RawQuery(observedEntities = Employee.class) LiveData<List<Employee>> getAllEmployeesWithLimit(SupportSQLiteQuery query); java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
  • 90. @Transaction @Dao public abstract class DepartmentDao { @Insert public abstract void insert(Department product); @Delete public abstract void delete(Department product); @Transaction public void insertAndDeleteInTransaction(Department newDepartment, Department oldDepartment) { // Anything inside this method runs in a single transaction. insert(newDepartment); delete(oldDepartment); } }
  • 91. Threading - Room 1.0 First thread Second Thread
  • 92. Threading - Room 1.0 First thread Second Thread WRITE
  • 93. Threading - Room 1.0 First thread Second Thread WRITE WAITING...
  • 94. Threading - Room 1.0 First thread Second Thread WRITE WAITING... READ
  • 95.
  • 96. Threading - Room 1.1 First thread Second Thread
  • 97. Threading - Room 1.1 First thread Second Thread WRITE READ
  • 99. Company id integer name text date integer latitude real longitude real hq_latitude real hq_longitude real Version 1
  • 100. Company id integer name text date integer latitude real longitude real hq_latitude real hq_longitude real ref_no text Version 2
  • 104. Version yVersion x Version 2Version 1 ------------------------------------------------------------ Migration
  • 105. // Upgrading database @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // oldVersion -> newVersion }
  • 106. // Upgrading database @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // oldVersion -> newVersion } “CLASSICAL” APPRO ACH
  • 107.
  • 108. final Migration MIGRATION_X_Y = new Migration(X, Y) { @Override public void migrate(SupportSQLiteDatabase database) { // your code here } };
  • 109. final Migration MIGRATION_X_Y = new Migration(X, Y) { @Override public void migrate(SupportSQLiteDatabase database) { // your code here } }; RO O M APPRO ACH
  • 110. static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { database.execSQL("ALTER TABLE Company " + " ADD COLUMN ref_no TEXT"); } };
  • 111. public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) .addMigrations(MIGRATION_1_2) .build(); } return INSTANCE; }
  • 112. public static AppDatabase getAppDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) .addMigrations(MIGRATION_1_2) .build(); } return INSTANCE; }
  • 113. Version 2Version 1 room_master_table id identity_hash 42 <v1_hash> room_master_table id identity_hash 42 <v2_hash> Migration
  • 114.
  • 115.
  • 116. /** * You can set annotation processor argument (room.schemaLocation) to tell Room to * export the schema into a folder. Even though it is not mandatory, it is a good * practice to have version history in your codebase and you should commit that file * into your version control system (but don't ship it with your app!). * */ //export schema javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] } }
  • 117. /** * Room will throw an IllegalStateException if you don’t provide a Migration. * */ if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .fallbackToDestructiveMigration() .build(); }
  • 118. /** * Room will throw an IllegalStateException if you don’t provide a Migration. * */ if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .fallbackToDestructiveMigration() .build(); }
  • 119. /** * Room will throw an IllegalStateException if you don’t provide a Migration. * */ if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "company-db") .fallbackToDestructiveMigrationFrom(int... startVersions) .build(); }
  • 120. Room Advantages Less boilerplate code SQL queries checked at compile time No db operations on the main thread Maintainable code Migration support
  • 122. ● Official docs: https://developer.android.com/topic/libraries/archite cture/room.html ● Google code samples and Youtube channel: https://github.com/googlesamples/android-architec ture-components ● CommonsWare: https://commonsware.com/AndroidArch/ ● Slides from: https://www.slidescarnival.com/ and gifs from: https://gifer.com Resources