Room Data Access Objects (DAO)
DAO
A Data Access Object (DAO) is an abstract class or interface that includes methods to define database queries.
DAOs provide the following advantages:
- No need to use queries
- Easy to mock
- Verified and Parsed at compile time
- Reduced boilerplate
DAO Annotations
Types:
- @Dao
- @Query
- @Insert
- @Delete
- @Update
Insert
@Dao // Required annotation for DAO to be recoginized by Room
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public void insertUsers(User... users);
@Insert
public void insertBothUsers(User user1, User user2);
@Insert
public void insertUsersAndFriends(User user, List<User> friends);
}
If the @Insert
method receives only 1 parameter, it can return a long, which is the new rowId for the inserted item. If the parameter is an array or a collection, it should return long[]
or List<Long>
instead.
Update
@Dao
public interface MyDao {
@Update
public void updateUsers(User... users);
}
Delete
@Dao
public interface MyDao {
@Delete
public void deleteUsers(User... users);
}
Query
Performs read/write operations on the database. Verified at compile time.
Simple Query
@Dao
public interface MyDao {
@Query("SELECT * FROM user")
public User[] loadAllUsers();
}
Passing parameters
you can include parameters passed into the method annotated with @Query, by appending a colon (:) to the parameter in the query string.
@Dao
public interface MyDao {
@Query("SELECT * FROM user WHERE age > :minAge")
public User[] loadAllUsersOlderThan(int minAge);
}
@Dao
public interface MyDao {
@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
public User[] loadAllUsersBetweenAges(int minAge, int maxAge);
@Query("SELECT * FROM user WHERE first_name LIKE :search "
+ "OR last_name LIKE :search")
public List<User> findUserWithName(String search);
}
subsets
public class NameTuple {
@ColumnInfo(name="first_name")
public String firstName;
@ColumnInfo(name="last_name")
public String lastName;
}
@Dao
public interface MyDao {
@Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();
}
Can be embedded instead.
Observable queries
return livedata to observe database.
@Dao
public interface MyDao {
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}
RxJava 2.0 integration
@Dao
public interface MyDao {
@Query("SELECT * from user where id = :id LIMIT 1")
public Flowable<User> loadUserById(int id);
}
Querying multiple tables Room will watch all tables for invalidation if they are flowable or livedata and can perform join tables.
@Dao
public interface MyDao {
@Query("SELECT * FROM book "
+ "INNER JOIN loan ON loan.book_id = book.id "
+ "INNER JOIN user ON user.id = loan.user_id "
+ "WHERE user.name LIKE :userName")
public List<Book> findBooksBorrowedByNameSync(String userName);
}
Using a POJO to store a join table object
@Dao
public interface MyDao {
@Query("SELECT user.name AS userName, pet.name AS petName "
+ "FROM user, pet "
+ "WHERE user.id = pet.user_id")
public LiveData<List<UserPet>> loadUserAndPetNames();
// You can also define this class in a separate file, as long as you add the
// "public" access modifier.
static class UserPet {
public String userName;
public String petName;
}
}
Kotlin RxJava
@Dao
interface UserDao {
/**
* Get a user by id.
* @return the user from the table with a specific id.
*/
@Query("SELECT * FROM Users WHERE userid = :id")
fun getUserById(id: String): Flowable<User>
/**
* Insert a user in the database. If the user already exists, replace it.
* @param user the user to be inserted.
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUser(user: User)
/**
* Delete all users.
*/
@Query("DELETE FROM Users")
fun deleteAllUsers()
}