Data Access Objects - DAO in Room
                 Note: This article is part of the advanced Room series which covers all the details about the Room persistence library. You can read all the articles here:
- Introduction to Room Persistent Library in Android
 - Data Access Objects - DAO in Room [You are here]
 - Entity Relationship in Room
 - How does Room work internally?
 - Room Database Migrations
 - Using Room with LiveData and other third-party libraries
 
So, let's get started.
In previous articles, we have covered how we can use Room persistence library to create a relational database very easily. Some of the advantages of using Room are compile-time query verification, no boilerplate code and easy integration with RxJava, LiveData and Kotlin Coroutines. All these advantages in Room are achieved using Data Access Objects or DAOs.
                  In this article, we going to discuss
                  
                   
                  or
                  
                    Data Access Objects
                   
                  
                   
                  in detail.
                 
                    DAOs
                   
                  
                  In Room,
                  
                   
                  or
                  
                    Data Access Objects
                   
                  
                   
                  are used to access your application’s persisted data. They are a better and modular way to access your database as compared to query builders or direct queries.
                 
                    DAOs
                   
                  
                  A DAO can be either an interface or an abstract class. If it’s an abstract class, it can optionally have a constructor that takes a
                  
                   
                  as its only parameter. Room creates each DAO implementation at compile time.
                 
                    
                     RoomDatabase
                    
                   
                  
You can perform multiple operations using DAO like Insertion, Updation, Deletion and making raw queries. Also, you can easily integrate LiveData, RxJava Observables, Kotlin Coroutines in DAOs.
Insertion
                  When you create a DAO method and annotate it with
                  
                   
                  , Room generates an implementation that inserts all parameters into the database in a
                  
                   single transaction.
                  
                 
                    
                     @Insert
                    
                   
                  
@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertUsers(vararg users: User)    @Insert
    fun insertBothUsers(user1: User, user2: User)    @Insert
    fun insertUsersAndFriends(user: User, friends: List<User>)
}
                 
                  
                   
                  annotation parameter signifies what to do if a conflict happens on insertion. It can take the following values:
                 
                    onConflict
                   
                  
- OnConflictStrategy.REPLACE : To replace the old data and continue the transaction.
 - OnConflictStrategy.ROLLBACK : To rollback the transaction.
 - OnConflictStrategy.ABORT : To abort the transaction. The transaction is rolled back.
 - OnConflictStrategy.FAIL : To fail the transaction. The transaction is rolled back.
 - OnConflictStrategy.NONE : To ignore the conflict.
 
Note: ROLLBACK and FAIL strategies are deprecated. Use ABORT instead.
Updation
                  When you create a DAO method and annotate it with
                  
                   
                  , Room generates an implementation that modifies a set of entities, given as parameters, in the database. It uses a query that matches against the primary key of each entity.
                 
                    
                     @
                    
                    
                     Update
                    
                   
                  
@Dao
interface UserDao {
    @Update(onConflict = OnConflictStrategy.REPLACE)
    fun updateUsers(vararg users: User)    @Update
    fun update(user: User)
}
                 Deletion
                  When you create a DAO method and annotate it with
                  
                   @
                   
                  , Room generates an implementation that removes a set of entities, given as parameters, from the database. It uses the primary keys to find the entities to delete.
                 
                    Delete
                   
                  
@Dao
interface UserDao {
    @Delete
    fun deleteUsers(vararg users: User)
}
                 Simple queries
                  
                   
                  is the main annotation used in DAO classes. It allows you to perform read/write operations on a database. Each
                  
                    
                     @Query
                    
                   
                  
                   
                  method is verified at compile time, so if there is a problem with the query, a compilation error occurs instead of a runtime failure.
                 
                    
                     @Query
                    
                   
                  
Room also verifies the return value of the query such that if the name of the field in the returned object doesn’t match the corresponding column names in the query response, Room alerts you in one of the following two ways:
- It gives a warning if only some field names match.
 - It gives an error if no field names match.
 
@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun loadAllUsers(): Array<User>
}
                 Passing parameters into the query
Parameters passed to the DAO methods can be used into the query written in @Query annotation.
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE age BETWEEN :minAge AND :maxAge")
    fun loadAllUsersBetweenAges(minAge: Int, maxAge: Int): Array<User>
    @Query("SELECT * FROM users WHERE first_name LIKE :search " +
           "OR last_name LIKE :search")
    fun findUserWithName(search: String): List<User>
}
                 Returning subsets of columns
You can also return subsets of columns from a query in Room.
data class NameTuple(
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)@Dao
interface UserDao {
    @Query("SELECT first_name, last_name FROM users")
    fun loadFullName(): List<NameTuple>
}
                 Direct cursor access
                  If your app’s logic requires direct access to the return rows, you can return a
                  
                   
                  object from your queries.
                 
                    
                     Cursor
                    
                   
                  
@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun loadAllUsers(): Cursor
}
                 Querying multiple tables
                  Some of your queries might require access to multiple tables to calculate the result. Room allows you to write any query, so you can also join tables. Furthermore, if the response is an observable data type, such as
                  
                   
                  or
                  
                    
                     Flowable
                    
                   
                  
                   
                  , Room watches all tables referenced in the query for invalidation.
                 
                    
                     LiveData
                    
                   
                  
@Dao
interface BookDao {
    @Query(
        "SELECT * FROM book " +
        "INNER JOIN loan ON loan.book_id = book.id " +
        "INNER JOIN user ON user.id = loan.user_id " +
        "WHERE users.name LIKE :userName"
    )
    fun findBooksBorrowedByNameSync(userName: String): List<Book>
}
                 Query return types
Room supports a variety of return types for query methods, including specialised return types for interoperability with specific frameworks or APIs.
                 
                  You can return
                  
                   
                  ,
                  
                    LiveData
                   
                  
                   
                  and
                  
                    Observable
                   
                  
                   
                  from query methods. Also, you can make a DAO method
                  
                   suspend function
                  
                  . These are discussed in separate articles.
                 
                    Flow
                   
                  
This is all about DAO in Room. Hope you enjoyed this blog. In the next blog, we will learn about Entity Relationship in Room .
You can also connect with me on LinkedIn , Twitter , Facebook and Github .
Thank You!!!