Room provides type conversions between native and boxed types, but does not allow object references between entities. This article explained how to use converters and why Room does not support object references.

Using type Converters

Sometimes you want to store custom data types in a database column. To support this custom type, provide a TypeConverter that can be converted between a defined type and a known type for Room to save.

For example, if we wanted to save Date, we could write the following TypeConverter to store the Unix equivalent timestamp in the database:

class Converters { @TypeConverter fun fromTimestamp(value: Long?) : Date? {returnvalue? .let { Date(it) } } @TypeConverter fun dateToTimestamp(date: Date?) : Long? {returndate? .time? .toLong() } }Copy the code

The previous example defined two functions, one to convert Date to Long and one to convert Long to Date. Room knows how to save Long, so you can use a converter to save dates.

Next, add the @Typeconverters annotation to the database class to apply the converter to the entities and DAOs you define:

@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}
Copy the code

Using these converters, you can use custom types in queries as if they were native types:

User

@Entity
data class User(private val birthday: Date?)
Copy the code

UserDao

@Dao
interface UserDao {
    @Query("SELECT * FROM user WHERE birthday BETWEEN :from AND :to")
    fun findUsersBornBetweenDates(from: Date, to: Date): List<User>
}
Copy the code

You can also limit @Typeconverters to single entities, DAOs, and DAO methods. See @typeconverters for details

Understand why Room does not allow references between objects

Key point: Room does not allow multiple entity references, instead you must explicitly request the data you need in your app.

Mapping relationships in a database to an object model is a common practice, and it works fine on the server side, even loading fields when the program accesses them.

However, on the client side, this lazy loading mode is not feasible because it often runs in the UI thread. Querying information on disk in the UI thread can cause serious performance problems. The UI thread has about 16ms to calculate and draw the view, so even if the query takes up only 5ms of that time, it might still not take enough time to draw the view and drop frames. If there is a separate transaction running in parallel, or if the disk is doing other intensive operations, the query will consume more time. If you don’t use lazy loading, you will get a lot of data that you don’t need, causing memory consumption problems.

Developers know how to combine app use cases to make object-relational mapping work better. Typically, developers share models between the app and the UI, but this approach doesn’t scale well because sharing models can create problems that developers can’t anticipate and debug as the UI changes.

For example, suppose a UI loads a collection of book objects, each with an author object. In the original design you might use lazy loading to retrieve the author of the book instance. The first search for the author field will query the database. After a while, you realize that you need to display the author name on the UI, so you can easily access it using the following code

authorNameTextView.text = book.author.name
Copy the code

However, this seemingly harmless change causes the author table to be queried on the main thread.

If author information is queried ahead of time, it is difficult to change how the data is loaded if it is no longer needed. For example, if your app doesn’t need to display author information, loading unnecessary data is a waste of memory space. If the author class references another class, such as the book class, the efficiency of the app is further reduced. To use Room reference multiple entities at the same time, you need to write a connection table query instead of creating a contains every entity pojos, this structure is a good model, combining with the Room powerful query authentication function, allowing your application at the time of loading the data consume fewer resources, so as to improve the performance of the application and the user experience.


0. Overview

1. Use Room entities to define data

2. Define relationships between objects

3. Create a view in the database

4. Use Room DAOs to access data

5. Migrate the database

6. Test the database

7. Reference complex data using Room