Configuring Room’s Database Access
We used RoomDatabase
to set up our database and get access to our DAO(s) for working with our entities. By default, RoomDatabase
will use the “framework” implementation of the support database APIs. However:
- We can tell it to use something else
- We can get control as part of the database setup, to configure the database manually, regardless of what support database API implementation we use
Get a Factory
With the framework’s Android SQLite API, many developers elect to use SQLiteOpenHelper
as their entry point. This handles creating and upgrading the database in a decent structured fashion. However, SQLiteOpenHelper
is not a requirement — developers could use static methods on SQLiteDatabase
, such as openOrCreateDatabase()
, to work with a SQLiteDatabase
without an associated SQLiteOpenHelper
.
The equivalent interface in the support database API is SupportSQLiteOpenHelper
, and it fills the same basic role.
With the support database API, working with a SupportSQLiteOpenHelper
is unavoidable. Whether you use it, or Room uses it, somebody sets up one of these. SupportSQLiteOpenHelper
fills a role similar to that of SQLiteOpenHelper
, providing a single point of control for creating and upgrading a database.
However, you do not create a SupportSQLiteOpenHelper
directly yourself. Instead, you ask a SupportSQLiteOpenHelper.Factory
to do that for you. Each implementation of the support database API should have a class that implements the SupportSQLiteOpenHelper.Factory
interface:
- The default Room implementation is
FrameworkSQLiteOpenHelperFactory
, from theandroid.arch.persistence:db-framework
artifact - CWAC-SafeRoom has
SafeHelperFactory
- The
AssetRoom
sample app hasAssetSQLiteOpenHelperFactory
- And so on
How you get an instance of that factory is up to the implementation of the support database API. In the case of FrameworkSQLiteOpenHelperFactory
and AssetSQLiteOpenHelperFactory
, you just create an instance via a no-parameter constructor. CWAC-SafeRoom offers a one-parameter constructor on SafeHelperFactory
, where you supply the passphrase as the parameter. SafeHelperFactory
also has a static fromUser()
method, for you to supply an Editable
with the passphrase, such as from an EditText
widget.
Regardless, one way or another, you will need to get an instance of a factory.
You can use the factory directly, bypassing all of Room. More often, though, you will want to use Room, but have Room use this support database API implementation.
For that, call openHelperFactory()
on the RoomDatabase.Builder
as part of setting it up:
// EditText passphraseField;
SafeHelperFactory factory=SafeHelperFactory.fromUser(passphraseField.getText());
StuffDatabase db=Room.databaseBuilder(ctxt, StuffDatabase.class, DB_NAME)
.openHelperFactory(factory)
.build();
Here, we are having Room use SafeHelperFactory
from CWAC-SafeRoom, so Room will wind up interacting with SQLCipher for Android.
Add a Callback
Regardless of whether we use openHelperFactory()
or not, we can also call addCallback()
on the RoomDatabase.Builder
to supply a RoomDatabase.Callback
to use. This callback can get control at two points:
- When the database file is created, via an
onCreate()
method on the callback - When the database file is opened, via an
onOpen()
method on the callback
In each case, you get a SupportSQLiteDatabase
object to use for manipulating the database. Room itself may not be completely ready for use — particularly in the onCreate()
callback — which is why you are not passed your RoomDatabase
subclass. Instead, you have to work with the database using the support database API directly.
For example, here we add a callback to manually create a table when the database is created:
RoomDatabase.Builder<BookDatabase> b=
Room.databaseBuilder(ctxt.getApplicationContext(), BookDatabase.class,
DB_NAME);
b.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
db.execSQL("CREATE VIRTUAL TABLE booksearch USING fts4(sequence, prose)");
}
});
BookDatabase books=b.build();
Normally, creating tables is the job of an @Entity
and its Room-generated code. In this case, we are creating an fts4
virtual table, one used for full-text searching. Room does not know how to create those, so we have to create it ourselves.
We will see more about full-text searching and Room later in the book.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.