Note: DO NOT PERFORM OPERATION ON MAIN THREAD AS APP WILL CRASH
Index
Update Gradle files
Next, you'll have to add the component libraries to your Gradle files.
- Apply the
kaptannotation processor Kotlin plugin by adding it in the plugins section defined on the top of yourbuild.gradle(Module: app) file.
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-kapt' }
- Some of the APIs you will use require 1.8
jvmTarget, so add that to theandroidblock as well.
Gradle may complain about missing or undefined versions at this point. They should be fixed with the next step.
Dependency
// For Room Dependencies implementation("androidx.room:room-runtime:2.6.1") kapt ("androidx.room:room-compiler:2.6.1") implementation("androidx.room:room-ktx:2.6.1") // For Coroutine implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
Create an Entity
@Entity(tableName = "word_table") class Word( @PrimaryKey @ColumnInfo(name = "word") val word: String )
Let's see what these annotations do:
@Entity(tableName ="word_table")Each@Entityclass represents a SQLite table.
- Annotate your class declaration to indicate that it's an entity.
- You can specify the name of the table if you want it to be different from the name of the class. This names the table "word_table".
@PrimaryKeyEvery entity needs a primary key. To keep things simple, each word acts as its own primary key.
@ColumnInfo(name ="word")Specifies the name of the column in the table if you want it to be different from the name of the member variable. This names the column word".
- Every property that's stored in the database needs to have public visibility, which is the Kotlin default.
Tip: You can autogenerate unique keys by annotating the primary key as follows:
@Entity(tableName = "word_table") class Word( @PrimaryKey(autoGenerate = true) val id: Int, @ColumnInfo(name = "word") val word: String )
Create the DAO
What is the DAO?
- In the DAO (data access object),
- you specify SQL queries and associate them with method calls.
- The compiler checks the SQL and generates queries from convenience annotations for common queries, such as
@Insert.
- Room uses the DAO to create a clean API for your code.
The DAO must be an interface or
abstract classBy default, all queries must be executed on a separate thread.
Room has Kotlin coroutines support. This allows your queries to be annotated with the
suspend modifier and then called from a coroutine or from another suspension function.Implement the DAO
Let's write a DAO that provides queries for:
- Getting all words ordered alphabetically
- Inserting a word
- Deleting all words
- Create a new Kotlin class file called
WordDao.
- Copy and paste the following code into
WordDaoand fix the imports as necessary to make it compile.
@Dao interface WordDao { // Live Data means it will run ob background thread byDefault @Query("SELECT * FROM word_table ORDER BY word ASC") fun getAlphabetizedWords(): LiveData<List<Word>> @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(word: Word) @Query("DELETE FROM word_table") suspend fun deleteAll() @Delete suspend fun deleteWord(word : Word) }
Let's walk through it:
WordDaois an interface; DAOs must either be interfaces or abstract classes.
- The
@Daoannotation identifies it as a DAO class for Room.
suspend fun insert(word: Word): Declares a suspend function to insert one word.
- The
@Insertannotation is a special DAO method annotation where you don't have to provide any SQL! (There are also@Deleteand@Updateannotations for deleting and updating rows, but you are not using them in this app.)
onConflict = OnConflictStrategy.IGNORE: The selected onConflict strategy ignores a new word if it's exactly the same as one already in the list. To know more about the available conflict strategies, check out the documentation.
suspend fun deleteAll(): Declares a suspend function to delete all the words.
- There is no convenience annotation for deleting multiple entities, so it's annotated with the generic
@Query.
@Query("DELETE FROM word_table"):@Queryrequires that you provide a SQL query as a string parameter to the annotation, allowing for complex read queries and other operations.
fun getAlphabetizedWords():LiveData<List<Word>>- A method to get all the words and have it return aListofWords.
@Query("SELECT * FROM word_table ORDER BY word ASC"): Query that returns a list of words sorted in ascending order.
Database abstract Class
@Database(entities =[Contact: :class], version = 1) abstract class ContactDatabase: RoomDatabase() { abstract fun contactDao() : ContactDAO companion object { @Volatile private var INSTANCE : ContactDatabase? = null fun getDatabase(context : Context) : ContactDatabase{ if(INSTANCE == null){ syncronized(this){ INSTANCE = Room.databaseBuilder(context.applicationContext, contactDatabase::class.java, "your_database_name").build() } } } } }
@Volatile - this annotation used to describe that this object can be used from multiple threads so if value changes then all thead will get its updated value.In Activity Class
lateinit var database : ContactDatabase database = ContactDatabase.getDatabase(this) // now by using databse objects dao object //we use database methods or we can provide implementation inside repository class. // like database.contactDao().insertData(`object`)
Repository
Type Converters
Like :
- Date to long
- image to byteArray
- object to string
- list to string
@TypeConverter- For Converter function
@TypeConverters('converter_class_name')- For Database Class
Relations Using Room
- One to One Relation
- One To Many Relation
- Many to Many Relation
One to one Relation
Example :
@Entity( tableName = "cart", // foreignKeys = [ForeignKey( // entity = Product::class, // parentColumns = ["id"], // childColumns = ["productId"], // onDelete = ForeignKey.CASCADE // )] ) data class CartItem( @PrimaryKey(autoGenerate = true) var id: Int = 0, var userId: String, var productId: Int, var productCount: Int, ) @Entity(tableName = "product") data class Product( @PrimaryKey var id: Int, var title: String, var price: Int, var rating: Double, var images: List<String> = listOf() )
- data Table To get Relational Response
data class CartWithProduct( @Embedded val cartItem: CartItem, // 1 @Relation( parentColumn = "productId", entityColumn = "id" ) val product: Product // to 1 )
- dao Query to get Result
- Here each cart has its relevent product details to fetch
@Query("select * from cart") @Transaction fun getCartData(): List<CartWithProduct> // LiveData<List<CartWithProduct>>
One To Many Relation
Example
data class UserWithCartItems( @Embedded val user: User, // 1 @Relation( parentColumn = "uid", entityColumn = "user_id" ) val cart: List<CartItem> // to Many Relation )
- here Query will be something like this
- fetch all carts of particular user (one user → Many Carts )
@Transaction @Query("SELECT * FROM user WHERE uid = :userId") suspend fun getSchoolWithStudents(userId: String) : List<UserWithCartItems>
Many to Many Relation
Example
data class SubjectWithStudents( @Embedded val subject: Subject, @Relation( parentColumn = "subjectName", entityColumn = "studentName", associateBy = Junction(StudentSubjectCrossRef::class) ) val students: List<Student> ) data class StudentWithSubjects( @Embedded val student: Student, @Relation( parentColumn = "studentName", entityColumn = "subjectName", associateBy = Junction(StudentSubjectCrossRef::class) ) val subjects: List<Subject> ) // Important // this need to define inside Database entities list Parameter @Entity(primaryKeys = ["studentName", "subjectName"]) data class StudentSubjectCrossRef( val studentName: String, val subjectName: String )
@Transaction @Query( value: "SELECT * FROM subject WHERE subjectName = :subjectName") suspend fun getStudentsOfSubject(subjectName: String) : List<SubjectWithStudents> @Transaction @Query( value: "SELECT * FROM student WHERE studentName = :studentName") suspend fun getSubjectsOfStudent(studentName: String) : List<StudentWi thSubj ects>
Migrations
- to update database From current version to new version
- we want to migrate like that we change db version and still data don’t lost.