These classes help your app save and get data easily. They organize how data is stored and used.
When you want to save user info like names or scores.
When your app needs to remember settings or preferences.
When you want to keep a list of items like tasks or notes.
When you need to update or delete saved data.
When you want to load data quickly without internet.
Syntax
Android Kotlin
1. Entity class: Defines a table in the database.
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: Int,
val name: String
)
2. DAO interface: Defines methods to access the database.
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Query("SELECT * FROM users")
suspend fun getAll(): List<User>
}
3. Database class: Holds the database and connects DAO.
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
Entity: Represents a table with columns.
DAO: Contains functions to add, read, update, or delete data.
Database: The main access point to your stored data.
Examples
This creates a table named 'tasks' with two columns: taskId and description.
Android Kotlin
@Entity(tableName = "tasks")
data class Task(
@PrimaryKey val taskId: Int,
val description: String
)
This DAO lets you add a task and get all tasks from the database.
Android Kotlin
@Dao
interface TaskDao {
@Insert
suspend fun addTask(task: Task)
@Query("SELECT * FROM tasks")
suspend fun getTasks(): List<Task>
}
This database class connects the Task entity and TaskDao for use in the app.
Android Kotlin
@Database(entities = [Task::class], version = 1)
abstract class TaskDatabase : RoomDatabase() {
abstract fun taskDao(): TaskDao
}
Sample App
This program creates an in-memory database, adds two users, and prints them.
Android Kotlin
import androidx.room.*
import android.content.Context
import kotlinx.coroutines.runBlocking
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: Int,
val name: String
)
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Query("SELECT * FROM users")
suspend fun getAll(): List<User>
}
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
fun main() {
// Normally, you get context from Android app, here we simulate
val context = androidx.test.core.app.ApplicationProvider.getApplicationContext<Context>()
val db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
.allowMainThreadQueries()
.build()
val userDao = db.userDao()
runBlocking {
userDao.insert(User(1, "Alice"))
userDao.insert(User(2, "Bob"))
val users = userDao.getAll()
users.forEach { println("User: ${it.id} - ${it.name}") }
}
}
OutputSuccess
Important Notes
Use @PrimaryKey to mark the unique ID for each entity.
DAO methods can be suspend functions to work with Kotlin coroutines for smooth background tasks.
Database class must be abstract and extend RoomDatabase.
Summary
Entity defines the data table structure.
DAO provides methods to access and modify data.
Database connects entities and DAOs for app use.
Practice
(1/5)
1. What is the main purpose of an Entity class in Android Room?
easy
A. To define the structure of a database table
B. To provide methods for database queries
C. To manage database connections
D. To handle UI updates
Solution
Step 1: Understand the role of Entity
An Entity class represents a table in the database by defining its columns and data types.
Step 2: Differentiate from DAO and Database
DAO provides query methods, and Database manages connections, so they are not the main purpose of Entity.
Final Answer:
To define the structure of a database table -> Option A
Quick Check:
Entity = Table structure [OK]
Hint: Entity = table layout definition in Room [OK]
Common Mistakes:
Confusing Entity with DAO
Thinking Entity manages database connections
Assuming Entity handles UI
2. Which of the following is the correct way to annotate a Kotlin data class as an Entity with a primary key named id?
easy
A. @Entity
data class User(@PrimaryKey val id: Int, val name: String)
B. @Entity
class User(val id: Int, val name: String)
C. @Entity(primaryKeys = ["id"])
data class User(val id: Int, val name: String)
D. @Entity
data class User(val id: Int @PrimaryKey, val name: String)
Solution
Step 1: Identify correct primary key annotation
The primary key must be annotated with @PrimaryKey on the property inside the data class.
Step 2: Check syntax correctness
@Entity
data class User(@PrimaryKey val id: Int, val name: String) correctly places @PrimaryKey before the id property in a data class annotated with @Entity.
Final Answer:
@Entity
data class User(@PrimaryKey val id: Int, val name: String) -> Option A
Quick Check:
Primary key uses @PrimaryKey annotation [OK]
Hint: Use @PrimaryKey before property inside @Entity data class [OK]
Common Mistakes:
Placing @PrimaryKey after property name
Using primaryKeys parameter incorrectly
Missing @PrimaryKey annotation
3. Given the DAO interface below, what will be the return type of getAllUsers() when called?
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAllUsers(): List<User>
}
medium
A. A Cursor object
B. A single User object
C. A list of User objects
D. A LiveData object
Solution
Step 1: Analyze the DAO method signature
The method getAllUsers() returns List<User>, which means a list of User objects.
Step 2: Understand Room query return types
Since the return type is explicitly List<User>, it returns a list, not a single object or LiveData.
Final Answer:
A list of User objects -> Option C
Quick Check:
Return type List<User> means list of users [OK]
Hint: Return type in DAO method shows data returned [OK]
Common Mistakes:
Confusing List<User> with LiveData
Expecting a single User instead of list
Thinking Room returns Cursor by default
4. Identify the error in the following Room database class:
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
fun getInstance(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, "app_db").build()
}
}
}
medium
A. Missing @Entity annotation on User class
B. No singleton pattern to prevent multiple database instances
C. Incorrect version number format
D. Database class should be an interface, not abstract class
Solution
Step 1: Review database class structure
The database class is abstract and correctly annotated with @Database and version number.
Step 2: Check instance creation method
The getInstance method creates a new database instance every time, lacking a singleton pattern to reuse one instance.
Final Answer:
No singleton pattern to prevent multiple database instances -> Option B
Quick Check:
Database instance should be singleton [OK]
Hint: Use singleton to avoid multiple database instances [OK]
Common Mistakes:
Not using singleton for database instance
Confusing abstract class with interface
Ignoring @Entity annotation on User
5. You want to create a Room database with two entities: User and Book. You also want to provide DAOs for both. Which is the correct way to define the database class?
hard
A. @Database(entities = [User::class, Book::class], version = 1)
abstract class AppDatabase {
abstract fun userDao(): UserDao
abstract fun bookDao(): BookDao
}
B. @Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun bookDao(): BookDao
}
C. @Database(entities = [User::class, Book::class], version = 1)
class AppDatabase {
fun userDao(): UserDao
fun bookDao(): BookDao
}
D. @Database(entities = [User::class, Book::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun bookDao(): BookDao
}
Solution
Step 1: Check entities list in @Database annotation
Both User and Book entities must be included in the entities array.
Step 2: Verify class declaration and DAO methods
The database class must be abstract and extend RoomDatabase, with abstract DAO methods.
Final Answer:
@Database(entities = [User::class, Book::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun bookDao(): BookDao
} -> Option D
Quick Check:
Entities list and abstract class with DAO methods [OK]
Hint: Include all entities and extend RoomDatabase abstract class [OK]
Common Mistakes:
Omitting one entity from entities list
Not extending RoomDatabase
Making database class non-abstract
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.