Room: แนวคิดหลัก Entity, DAO และการทำงานกับฐานข้อมูล

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-04 เวลาอ่าน: 8 นาที

Room เป็นไลบรารีสำหรับทำงานกับ SQLite ใน Android ซึ่งเป็นส่วนหนึ่งของ Jetpack โดยให้เลเยอร์นามธรรมเหนือ SQLite ดั้งเดิม ทำให้การสร้างตาราง การดำเนินการค้นหา และการแปลงข้อมูลเป็นวัตถุ Kotlin และ Java เป็นอัตโนมัติ ตาม Android Developers Room จะคอมไพล์คำสั่ง SQL ในเวลาสร้าง ตรวจสอบความถูกต้องของไวยากรณ์และความสัมพันธ์ระหว่าง Entity และตาราง

ประเด็นสำคัญ

  • Room คือไลบรารี ORM ของ Jetpack สำหรับทำงานกับ SQLite ในแอปพลิเคชัน Android
  • Entity คือคลาสที่มีคำอธิบายประกอบ @Entity แต่ละอินสแตนซ์สอดคล้องกับแถวในตาราง
  • DAO คือวัตถุเข้าถึงข้อมูลที่มีเมธอดที่มีคำอธิบายประกอบสำหรับคำสั่ง SQL
  • Database คือคลาสนามธรรมที่สืบทอด RoomDatabase เชื่อมโยง Entity และ DAO
  • การโยกย้าย คือกลไกในการเปลี่ยนแปลงสคีมาฐานข้อมูลอย่างปลอดภัยโดยไม่สูญเสียข้อมูลผู้ใช้

Room คืออะไรและทำไมจึงจำเป็น

Room คือไลบรารีการคงอยู่ของ Android Jetpack ที่ให้การแมปวัตถุ-เชิงสัมพันธ์สำหรับ SQLite Room แก้ปัญหาหลักสามประการของ SQLite ดั้งเดิม: การเขียนโค้ดต้นแบบปริมาณมากสำหรับสร้างตาราง การขาดการตรวจสอบคำสั่ง SQL ในเวลาคอมไพล์ และการแปลง Cursor เป็นวัตถุด้วยตนเอง

ไลบรารีใช้ตัวประมวลผลคำอธิบายประกอบ (kapt หรือ KSP) ที่สร้างการใช้งานของคลาสนามธรรม RoomDatabase และ DAO ในเวลาสร้าง สิ่งนี้ทำให้มั่นใจว่าข้อผิดพลาดทางไวยากรณ์ใน SQL และความไม่ตรงกันของชนิดถูกค้นพบก่อนเรียกใช้แอปพลิเคชัน แทนที่จะเป็นในรันไทม์หลังจากเผยแพร่บน Google Play

ตาม Google I/O 2023 Room ถูกใช้ใน 68% ของแอปพลิเคชัน Android ที่ทำงานกับข้อมูลภายในเครื่อง เป็นมาตรฐานสำหรับการจัดเก็บข้อมูลบนอุปกรณ์ที่ Google แนะนำสำหรับโปรเจกต์ใหม่ทั้งหมด — แทนที่ SQLiteOpenHelper และ ContentProvider ที่ล้าสมัย

นำ Room ไปใช้ในโปรเจกต์ที่ต้องการแคชข้อมูลภายในเครื่องจากเซิร์ฟเวอร์ โหมดออฟไลน์ หรือการจัดเก็บข้อมูลผู้ใช้ที่มีโครงสร้างพร้อมความสามารถในการดำเนินการคำสั่ง SQL ที่ซับซ้อน

Room เป็นส่วนหนึ่งของ Android Jetpack และได้รับการแนะนำอย่างเป็นทางการโดย Google สำหรับโปรเจกต์ใหม่ทั้งหมดที่ทำงานกับข้อมูลภายในเครื่อง แตกต่างจาก Realm หรือ ObjectBox Room ใช้ SQLite ดั้งเดิม ซึ่งรับประกันความเข้ากันได้กับเครื่องมือฐานข้อมูลของบริษัทอื่นใด ๆ ตั้งแต่ DB Browser ถึง DataGrip นักพัฒนาสามารถเปิดไฟล์ .db ของแอปพลิเคชันและดำเนินการคำสั่ง SQL ได้โดยตรง ซึ่งช่วยให้การดีบักและวิเคราะห์ข้อมูลระหว่างการพัฒนาง่ายขึ้น

Entity และคำอธิบายประกอบใน Room

Entity คือคลาสข้อมูลที่มีคำอธิบายประกอบ @Entity ซึ่ง Room แปลงเป็นตารางฐานข้อมูล แต่ละฟิลด์ของคลาสกลายเป็นคอลัมน์ของตาราง และแต่ละอินสแตนซ์กลายเป็นแถว Room ใช้รีเฟลกชันเพื่อเข้าถึงฟิลด์ ดังนั้นจึงจำเป็นต้องมีคำอธิบายประกอบ @PrimaryKey สำหรับตัวระบุที่จำเป็น

คำอธิบายประกอบหลัก

คำอธิบายประกอบ @Entity บอก Room ว่าคลาสเป็นตาราง พารามิเตอร์ tableName กำหนดชื่อตารางหากแตกต่างจากชื่อคลาส @PrimaryKey กำหนดคีย์หลักพร้อมรองรับการสร้างอัตโนมัติผ่าน autoGenerate = true

kotlin
@Entity(tableName = "users")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    @ColumnInfo(name = "full_name")
    val name: String,
    @Ignore
    val tempData: String?
)

@ColumnInfo ระบุชื่อคอลัมน์ในตารางหากแตกต่างจากชื่อฟิลด์ Kotlin @Ignore ไม่รวมฟิลด์ออกจากตาราง — ฟิลด์นั้นจะไม่ถูกบันทึกลงฐานข้อมูล @ForeignKey อธิบายคีย์ต่างประเทศสำหรับความสัมพันธ์ระหว่างตารางกับการดำเนินการแบบเรียงซ้อนเมื่อลบหรืออัปเดต

Room รองรับวัตถุที่ซ้อนกันผ่านคำอธิบายประกอบ @Embedded ฟิลด์ของคลาสที่ซ้อนกันจะขยายเป็นคอลัมน์ของตารางหลักด้วยคำนำหน้าเพื่อหลีกเลี่ยงความขัดแย้งของชื่อ ตัวอย่างเช่น คลาส Address ที่มีฟิลด์ city และ street ฝังอยู่ใน User จะสร้างคอลัมน์ address_city และ address_street ในตาราง users ทำให้ไม่จำเป็นต้องมีตารางแยกสำหรับวัตถุค่าอย่างง่าย

ตัวแปลงชนิด

Room รองรับเฉพาะชนิดดั้งเดิมและตัวหุ้มเท่านั้น สำหรับจัดเก็บลิสต์ Date หรือชนิดที่กำหนดเอง ให้ใช้ @TypeConverter — เมธอดแบบสแตติกสำหรับแปลงระหว่างชนิดที่กำหนดเองและชนิดดั้งเดิมของ SQLite ตัวอย่างเช่น ระหว่าง List และสตริง JSON

DAO และคำสั่ง SQL

DAO (วัตถุเข้าถึงข้อมูล) คืออินเทอร์เฟซหรือคลาสนามธรรมที่มีคำอธิบายประกอบ @Dao ซึ่งมีเมธอดสำหรับเข้าถึงข้อมูล แต่ละเมธอดมีคำอธิบายประกอบด้วยการดำเนินการ SQL: @Insert, @Update, @Delete หรือ @Query พร้อมคำสั่ง SQL ที่ชัดเจน

@Query พร้อมการตรวจสอบในเวลาคอมไพล์

คำอธิบายประกอบ @Query รับสตริง SQL ที่ Room ตรวจสอบในเวลาคอมไพล์เพื่อความถูกต้องของไวยากรณ์และการจับคู่ชื่อคอลัมน์กับฟิลด์ Entity Room รองรับคำสั่งแบบมีพารามิเตอร์ผ่านไวยากรณ์ :paramName

kotlin
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :userId")
    suspend fun getUserById(userId: Int): User?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Query("SELECT * FROM users ORDER BY name ASC")
    fun getAllUsers(): Flow<List<User>>
}

@Insert รองรับตัวเลือก OnConflictStrategy สำหรับจัดการความขัดแย้งเมื่อแทรกเรกคอร์ดที่ซ้ำกัน Flow เป็นชนิดส่งคืนให้การอัปเดต UI เชิงโต้ตอบทุกครั้งที่มีการเปลี่ยนแปลงข้อมูลในตาราง — การสมัครรับข้อมูลจะเริ่มใหม่โดยอัตโนมัติเมื่อมีการ INSERT, UPDATE หรือ DELETE

@Transaction สำหรับการดำเนินการที่ซับซ้อน

คำอธิบายประกอบ @Transaction รับประกันการดำเนินการแบบอะตอมมิกของการดำเนินการหลายรายการในบล็อกธุรกรรมเดียว Room ล็อกฐานข้อมูลระหว่างการดำเนินการ ป้องกันสภาวะการแข่งขันเมื่อเข้าถึงพร้อมกันจากหลายเธรด

Database และการโยกย้ายสคีมา

RoomDatabase คือคลาสนามธรรมที่รวม Entity และ DAO เข้าเป็นจุดเข้าถึงฐานข้อมูลเดียว สร้างขึ้นผ่าน Room.databaseBuilder พร้อมเวอร์ชันสคีมาและรายการคลาส Entity ควรสร้างอินสแตนซ์ฐานข้อมูลเป็นซิงเกิลตันผ่านตัวแทนขี้เกียจเพื่อหลีกเลี่ยงการเชื่อมต่อหลายครั้ง

การโยกย้าย

การโยกย้าย ใน Room คือคลาส Migration ที่อธิบายสคริปต์ SQL สำหรับการเปลี่ยนจากเวอร์ชันสคีมาเก่าไปยังเวอร์ชันใหม่ หากไม่ได้ระบุการโยกย้ายเมื่อสคีมาเปลี่ยนแปลง Room จะ throw IllegalStateException ซึ่งป้องกันการสูญเสียข้อมูลผู้ใช้โดยไม่ได้ตั้งใจเมื่ออัปเดตแอปพลิเคชัน

kotlin
val migration_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE users ADD COLUMN age INTEGER NOT NULL DEFAULT 0")
    }
}

val db = Room.databaseBuilder(
    getApplication(),
    AppDatabase::class.java,
    "app_database"
).addMigrations(migration_1_2)
 .build()

สำหรับการพัฒนา คุณสามารถใช้ fallbackToDestructiveMigration ซึ่งจะลบฐานข้อมูลเก่าและสร้างใหม่เมื่อเวอร์ชันไม่ตรงกัน โหมดนี้มีไว้สำหรับการดีบักเท่านั้น — รุ่นโปรดักชันต้องรวมการโยกย้ายที่เหมาะสม

สำหรับการทดสอบฐานข้อมูล Room มีคลาสพิเศษ Room.inMemoryTestBuilder ที่สร้างฐานข้อมูลในหน่วยความจำโดยไม่บันทึกลงดิสก์ หลังจากการทดสอบแต่ละครั้งเสร็จสมบูรณ์ ฐานข้อมูลจะถูกทำลายโดยอัตโนมัติ ทำให้มั่นใจได้ถึงการแยกสถานการณ์การทดสอบอย่างสมบูรณ์ เมื่อรวมกับไลบรารี android-arch-core-testing นักพัฒนาสามารถจัดการวงจรชีวิตของฐานข้อมูลและตรวจสอบความถูกต้องของการโยกย้ายโดยไม่ต้องทำความสะอาดสถานะด้วยตนเอง

ประสิทธิภาพของ Room ขึ้นอยู่กับโครงสร้างคำสั่งและดัชนีโดยตรง สำหรับการวิเคราะห์คำสั่งที่ช้า Room มีแฟล็ก enableQueryCallback ซึ่งบันทึกคำสั่ง SQL ทั้งหมดพร้อมเวลาในการดำเนินการ นักพัฒนาสามารถใช้บันทึกนี้เพื่อค้นหาคำสั่งที่ใช้เวลานานกว่า 100 มิลลิวินาทีและปรับให้เหมาะสมโดยเพิ่มดัชนีผสมผ่านคำอธิบายประกอบ @Index ใน @Entity หรือเขียนคำสั่งย่อยใหม่เป็นการดำเนินการ JOIN โดยตรงโดยใช้ @Relation

Room ยังรองรับการเข้ารหัสฐานข้อมูลผ่าน SQLCipher การเพิ่มไลบรารี net.zetetic:android-database-sqlcipher และใช้ SupportFactory แทนมาตรฐาน จะให้การเข้ารหัสที่โปร่งใสของข้อมูลทั้งหมดบนดิสก์โดยไม่เปลี่ยนคำสั่ง DAO หรือโครงสร้าง Entity ซึ่งจำเป็นสำหรับแอปพลิเคชันที่จัดการข้อมูลส่วนบุคคลของผู้ใช้และสอดคล้องกับ GDPR และกฎหมายของรัฐบาลกลางรัสเซีย 152-FZ เกี่ยวกับการคุ้มครองข้อมูลส่วนบุคคล รหัสผ่านการเข้ารหัสสามารถจัดเก็บใน Android Keystore เพื่อป้องกันการดึงข้อมูลผ่านเครื่องมือบนอุปกรณ์ที่รูท

Room กับ Kotlin Coroutines และ Flow

Room รองรับ Kotlin Coroutines ตั้งแต่เวอร์ชัน 2.1 เมธอด DAO สามารถเป็นฟังก์ชัน suspend ที่ดำเนินการคำสั่งในเธรดพื้นหลังโดยไม่บล็อกเธรดหลัก Room จัดการตัวจัดส่งโดยอัตโนมัติ โดยใช้ Dispatchers.IO สำหรับคำสั่งอ่านและเขียน

สำหรับคำสั่งเชิงโต้ตอบ Room จะส่งคืน Flow — สตรีมข้อมูลเย็นที่ปล่อยค่าใหม่ทุกครั้งที่มีการเปลี่ยนแปลงในตารางที่เกี่ยวข้อง ViewModel สมัครรับ Flow ผ่าน stateIn หรือ collect ให้การอัปเดต UI อัตโนมัติโดยไม่ต้องแจ้งอะแดปเตอร์ด้วยตนเอง

Room ยังรองรับ Paging 3 ผ่านการใช้งาน PagingSource พิเศษที่โหลดข้อมูลทีละหน้าจาก SQLite ซึ่งมีประสิทธิภาพสำหรับรายการขนาดใหญ่ที่มีเรกคอร์ดนับพัน: Paging 3 โหลดเฉพาะแถวที่มองเห็นบนหน้าจอและอัปเดตโดยอัตโนมัติเมื่อมีการเปลี่ยนแปลงในฐานข้อมูล

ใช้ Paging 3 กับ Room สำหรับแสดงฟีดข่าว บันทึกการดำเนินการ หรือรายการสินค้าที่มีการเข้าถึงแบบออฟไลน์และการเลื่อนแบบไม่สิ้นสุด

คำถามที่พบบ่อย

Room แตกต่างจาก SQLiteOpenHelper อย่างไร?

Room ทำให้การสร้างตาราง การแปลง Cursor เป็นวัตถุ และการตรวจสอบ SQL ในเวลาคอมไพล์เป็นอัตโนมัติ SQLiteOpenHelper ต้องเขียนสคีมาด้วยตนเอง จัดการ Cursor และไม่มีการตรวจสอบคำสั่งก่อนเรียกใช้แอปพลิเคชัน ซึ่งเพิ่มความเสี่ยงของข้อผิดพลาด

ฉันจำเป็นต้องเขียนการโยกย้ายสำหรับทุกการเปลี่ยนแปลงสคีมาหรือไม่?

ใช่ เมื่อเปลี่ยน Entity (เพิ่ม/ลบฟิลด์ เปลี่ยนชนิด) จำเป็นต้องมีการโยกย้าย หากไม่มี Room จะ throw IllegalStateException เมื่อเริ่มต้น สำหรับการพัฒนา คุณสามารถเปิดใช้ fallbackToDestructiveMigration แต่รุ่นโปรดักชันต้องมีสคริปต์การโยกย้ายที่ถูกต้อง

Room รองรับความสัมพันธ์ระหว่างตารางหรือไม่?

Room รองรับ @ForeignKey สำหรับการดำเนินการแบบเรียงซ้อนและ @Relation สำหรับวัตถุที่ซ้อนกัน สำหรับคำสั่ง JOIN ที่ซับซ้อน ให้ใช้คำอธิบายประกอบ @Transaction กับ @Query ที่ส่งคืน POJO พร้อมเอนทิตีที่ซ้อนกันผ่าน @Embedded และ @Relation

ฉันสามารถใช้ Room กับ Java โดยไม่มี Kotlin ได้หรือไม่?

ใช่ Room เข้ากันได้อย่างสมบูรณ์กับ Java แทนที่จะใช้ฟังก์ชัน suspend ให้ใช้ LiveData หรือ RxJava Observable แทน Flow ให้ใช้ LiveData Room กับ Java รองรับคำอธิบายประกอบเดียวกันทั้งหมด แต่ต้องใช้โค้ดต้นแบบมากกว่าสำหรับการดำเนินการแบบอะซิงโครนัส

การเข้ารหัสฐานข้อมูล Room ทำงานอย่างไร?

Room รองรับการเข้ารหัสผ่าน SQLCipher โดย Zetetic แทนที่จะใช้ Room.databaseBuilder ให้ใช้ SupportFactory จากไลบรารี net.zetetic:android-database-sqlcipher โดยส่งรหัสผ่านการเข้ารหัส ข้อมูลทั้งหมดบนดิสก์จะถูกเข้ารหัสอย่างโปร่งใสสำหรับคำสั่ง DAO

สรุป

  • Room คือไลบรารี ORM ของ Jetpack สำหรับ SQLite พร้อมการตรวจสอบ SQL ในเวลาคอมไพล์
  • @Entity อธิบายตาราง @PrimaryKey คือตัวระบุ @ColumnInfo คือชื่อคอลัมน์
  • @Dao มีเมธอดพร้อม @Query, @Insert, @Update และ @Delete สำหรับเข้าถึงข้อมูล
  • RoomDatabase รวม Entity และ DAO สร้างขึ้นผ่าน Room.databaseBuilder
  • การโยกย้าย (Migration) อธิบายสคริปต์ SQL สำหรับการเปลี่ยนแปลงสคีมาโดยไม่สูญเสียข้อมูล
  • Room รองรับ Kotlin Coroutines (suspend) และ Flow สำหรับการอัปเดต UI เชิงโต้ตอบ
  • สำหรับรายการขนาดใหญ่ ให้ใช้ Paging 3 กับ Room ผ่าน PagingSource สำหรับการโหลดแบบแบ่งหน้า

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม