Chapters

Hide chapters

Saving Data on Android

First Edition · Android 10 · Kotlin 1.3 · AS 3.5

Before You Begin

Section 0: 3 chapters
Show chapters Hide chapters

Using Firebase

Section 3: 11 chapters
Show chapters Hide chapters

6. Entity Definitions
Written by Aldo Olivares

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

In the previous chapter, you learned the architecture behind Room. You also learned about ORMs, Jetpack Architecture Components and the advantages and disadvantages of SQLite.

In this chapter, you’ll cover all you need to know about Room entities. Along the way, you will learn:

  • The properties of SQLite tables.
  • How to add Room’s dependencies to your gradle files.
  • How to create SQLite tables using Room annotations.
  • How to define primary keys and column names.

I hope you’re ready to get started!

Note: This chapter assumes you have a basic knowledge of Kotlin and Android. If you’re new to Android, you can find a lot of beginner Android content to get you started on our site at https://www.raywenderlich.com/category/android. If you know Android, but are unfamiliar with Kotlin, take a look at our tutorial, “Kotlin for Android: An Introduction” at https://www.raywenderlich.com/174395/kotlin-for-android-an-introduction-2.

Getting started

Have you ever played trivia games and thought, “There should be a game like this but with questions for Android developers”? Well, the sample app you will be working on, DroidQuiz, is a trivia game that allows you to answer a series of questions to test your knowledge of Android.

In this chapter, you’re only going to build entities that represent the tables of your database. If you’ve had some previous experience with SQL, you probably know that this can be somewhat annoying or painstaking to accomplish. Additionally, in “Chapter 3, SQLite Database,” you saw how, with SQL syntax, it can sometimes be hard to deduce which parts of it caused an error (if by some chance you get one). The Room database, and its annotation-driven system of creating entities and queries, make this process tremendously easier.

Start by opening the starter project for this chapter in Android Studio 3.2 or greater by going to File ▸ New ▸ Import Project, and selecting the build.gradle file in the root of the project.

Once the starter project finishes loading and building, run the app on a device or an emulator.

Right now, the app is just an empty canvas, but that is about to change!

Tables and entities

Most databases consist of tables and entities. If you were to draw a parallel with object-oriented programming, you could think of entities as a class definition, which defines what the objects in the table should look like and how their respective properties behave. Once you create those objects — instances of classes, or entities in your case — you can store somewhere in memory, which is the table. The table as such is a container for all the created objects of some entity type.

Tables

If you reached this section of the book you’re probably already familiar with relational databases, tables and SQLite. However, it is important to review other key concepts before you proceed to create your entities using Room.

Entities

To create a table using Room you need to create an entity, just like you did above. Entities in Room are defined by using a series of different annotations on classes. The following are the most common annotations that you will use when defining an entity:

@Entity

The @Entity annotation declares that the annotated class is a Room entity. For each entity, a table is created in the associated SQLite database to save your data. To add the annotation, simply use the following approach:

@Entity
data class Movie(
    //...
)
@Entity(tableName = "movies")
data class Movie(
    //...
)

@PrimaryKey

The @PrimaryKey annotation allows you to define a primary key for your table. It is very important to remember that each entity in Room must have at least one field defined as primary key:

@Entity
data class Movie(
    @PrimaryKey var id: Int,
    var title: String?,
    var description: String?,
    var releaseDate: String?,
    var rating: Float
)
@Entity
data class Movie(
    @PrimaryKey(autogenerate = true) var id: Int,
    var title: String?,
    var description: String?,
    var releaseDate: String?,
    var rating: Float
)

@ColumnInfo

In the same way that the tableName property of the @Entity annotation allows you to customize the name of your table, the @ColumnInfo annotation lets you change the name of your columns — class properties in Kotlin:

@Entity
data class Movie(
    @PrimaryKey(autogenerate = true) var id: Int,
    var title: String?,
    var description: String?,
    @ColumnInfo(name = "release_date") var releaseDate: String?,
    var rating: Float
)

@Ignore

Room translates all of your class properties into database columns by default. If there is a field that you don’t want to be converted into a column, you can use the @Ignore annotation to tell Room to ignore it:

@Entity
data class Movie(
    @PrimaryKey(autogenerate = true) var id: Int,
    var title: String?,
    var description: String?,
    @ColumnInfo(name = "release_date") var releaseDate: String?,
    var rating: Float,
    @Ignore var poster: Bitmap?
)
@Entity(ignoredColumns = arrayOf("poster"))
data class Movie(
    @PrimaryKey(autogenerate = true) var id: Int,
    var title: String?,
    var description: String?,
    @ColumnInfo(name = "release_date") var releaseDate: String?,
    var rating: Float,
    var poster: Bitmap?
)

@Embedded

The @Embedded annotation can be used on an entity’s field to tell Room that the properties on the annotated object should be represented as columns on the same entity.

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    val street: String?,
    val state: String?,
    val city: String?,
    @ColumnInfo(name = "post_code") val postCode: Int
)
data class Address(
    val street: String?,
    val state: String?,
    val city: String?,
    @ColumnInfo(name = "post_code") val postCode: Int
)

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    @Embedded val address: Address?
)

Creating your entities

Since you’ll be working on with Room, make sure you’ve opened the starter project, located in the entity-definitions ▸ projects folder.

//Room
implementation "androidx.room:room-common:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-runtime:$room_version"

@Entity(tableName = "questions") // 1
data class Question(
    @PrimaryKey(autoGenerate = true) // 2
    @ColumnInfo(name = "question_id") // 3
    var questionId: Int,
    val text: String
)
@Entity(tableName = "answers")
data class Answer(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "answer_id")
    val answerId: Int,
    @ColumnInfo(name = "question_id")
    val questionId: Int,
    @ColumnInfo(name = "is_correct")
    val isCorrect: Boolean,
    val text: String
)
@Database(entities = [(Question::class), (Answer::class)], version = 1)
abstract class QuizDatabase : RoomDatabase()
class QuizApplication : Application() {
  // 1
  companion object {
    lateinit var database: QuizDatabase // 2
      private set
  }

  override fun onCreate() {
    super.onCreate()
    database = Room
        .databaseBuilder(
            this,
            QuizDatabase::class.java,
            "quiz_database"
        ) // 3
        .build()
  }
}
android:name=".QuizApplication"

Key points

Where to go from here?

In this chapter, you learned a lot about SQLite tables, Room and entities. If you want to learn more about entities, I suggest the following resources:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now