DEV Community

Cover image for Creating a Database entity with Android and Kotlin
Tristan Elliott
Tristan Elliott

Posted on

Creating a Database entity with Android and Kotlin

Introduction

  • This series is not going to be in any particular order, so feel free to read whatever blog post you want. Anytime I find something that I think could use a blog post, I will write one and put it here

Creating the entity

  • So by the end of the tutorial you will be able to understand the code below:
@Entity
data class Calf(
    @PrimaryKey(autoGenerate = true)
    val id: Long,
    @ColumnInfo(name="tag_number")
    val tagNumber: Number,
    @ColumnInfo(name="details")
    val details:String,
    @ColumnInfo(name="born")
    val calved: Long = System.currentTimeMillis()
) {
    val createdDateFormatted: String
        get() = DateFormat.getDateInstance().format(calved)

}
Enter fullscreen mode Exit fullscreen mode
  • A little confusing right? Well, actually its not too bad, all we have to understand is first understand a little bit of Kotlin and the Android Room database

Kotlin Data class

  • First things first, lets talk about the keywords data class Calf (sorry about the naming convention, my app is cow themed). So as the documentation states: The main purpose of a data class is to hold data as well as extra functionality. Some of that extra functionality comes in the form of 3 methods:
    1) equals() : used for comparing instances
    2) hashCode() : Used for using objects as keys in hash-based containers such as Hashmaps
    3)toString() : used for generating string representation showing all the fields in declaration order.

  • The usefulness of these methods may not seem important to us on the surface. However, they will get used quite often under the hood.

  • Now obviously these auto generated methods need properties to act on. So the question comes up, Where do these properties come from ?. The answer is the Primary Constructor

Primary Constructor

  • In Kotlin there are two types of constructors:
    1) Primary constructor (We ARE interested in)
    2) Secondary constructor (We are NOT interested in)

  • The primary constructor is a part of the class header which is basically everything before the {...} curly brackets(body) of a class. The primary constructor has a very concise syntax which means that there are only certain things we can place inside of it. So that means no initialization code, initialization code goes inside of init() methods. What the primary constructor allows us to do is define properties for the class. For us the properties are everything defined in the primary constructor with a val keyword, like val id: Long. The thing that is really important here is the val keyword, because it creates an immutable reference property. Meaning 2 things:
    1) : The value can not be reassigned once it is assigned
    2) : A automatic getter(retrieval read only) method is created by Kotlin because a val property is read only.

  • if you need to reassign the value, then you should define the property with the var keyword.

Quick recap

  • So we define a data class with data class Calf, with gives us a lot of extra functionality in the form of methods. The properties that those methods use are defined in the primary constructor. Which is everything in the Calf(...) and starts with the val keyword. The val keyword means that Kotlin will automatically generate a property for the class that is read-only, so we can not reassign it and we can only access it through the getter methods(auto generated for us).

Database entity

  • So for persistence we are using the Room library which simplifies the mapping our data classes to the underlying SQL database.

  • To create a database entity we need to annotate a class with the @Entity annotation. We also need to define a field with the @PrimaryKey annotation, which acts as the unique identifier within the underlying database. With, @PrimaryKey(autoGenerate = true) We are saying that we want this value to be generated by the database itself, which is awesome because that is one less thing that we have to worry about .Technically speaking those are the only two annotations that are required. So as long as you have those annotations all the other properties defined in the primary constructor will be mapped to columns in the underlying database. The @ColumnInfo(name="details") annotation is not required, I just like it to remind myself what the fields name is in the database.

Custom accessor method

  • So the last thing that we have to talk about is this chunk of code:
val createdDateFormatted: String
        get() = DateFormat.getDateInstance().format(calved)

Enter fullscreen mode Exit fullscreen mode

-Remember that with the val keyword we are defining a immutable reference variable. Kotlin will then automatically create a getter(read only) method for the createdDateFormatted variable. We then override that method with the get() method. Then thanks to DateFormat.getDateInstance().format(calved) anytime we access createdDateFormatted we will get a properly formatted date

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.

Top comments (0)