Floor — มันคืออะไร, ORM เทือบ SQLite ใน Flutter

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

Floor — ORM (Object-Relational Mapping) สำหรับ Flutter ที่ให้ชั้นที่ได้รับการกำหนดชนิดเทือบ SQLite ต่างจากคำสั่ง SQLite ดิบ Floor สร้างคลาส DAO จากโมเดล Dart ที่ได้รับการเอนโนเทชัน ตามข้อมูลจาก Pub.dev, 2024, Floor ถูกใช้ในโครงการ Flutter มากกว่า 3500 โครงการ และเป็นหนึ่งในสามอันดับของโซลูชั่น ORM ยอดนิยมที่สุดสำหรับการจัดเก็บข้อมูลในเครืองควบคุมพร้อมกับ drift และ hive

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

  • Floor — ORM เทือบ SQLite พร้อมการสร้างโค้ด DAO และ Entity ผ่านเอนโนเทชัน
  • ความปลอดภัยของชนิด — คำสั่งถูกตรวจสอบในขณะแปลงคอม์ไพเลอร์ กำจัดข้อผิดพลาด SQL ขณะรันไทม์
  • แบบ DAO — Data Access Object ห่อหุ้มคำสั่ง SQL ไว้ในเมธอด Dart
  • การย้ายข้าม — รองรับการกำกับเวอร์ชันโครงสร้าง SQLite ในตัว
  • การตอบสนอง — คำสั่ง Flow ผ่าน Stream สำหรับการอัพเดต UI โดยอัตโนมัติ

Floor คืออะไร?

Floor เป็นไลบรารี ORM สำหรับ Flutter และ Dart ที่สร้างบน SQLite โดยใช้เอนโนเทชันในการอธิบายองค์ประกอบ (Entity), Data Access Objects (DAO) แลฐานข้อมูล (Database) การสร้างโค้ดจะดำเนินการผ่าน build_runner และ floor_generator — ตัวแปลงจะสร้างการนำไปใช้ของ DAO และคลาสจัดการฐานข้อมูล ต่างจาก sqflite ดิบ Floor จะกำจัดความต้องการแปลงด้วยตนจาก ResultSet ไปเป็นอ็อบเจกต์ Dart โดยแมปคอลัมน์ไปยังฟีลด์ Entity โดยอัตโนมัติผ่านการสะท้อนชนิด

Floor ทำตามแบบ Repository + DAO ที่นักพัฒนา Android คุ้นเคยจาก Room แต่ละตารางจะแสดงโดยคลาส Dart ที่มีเอนโนเทชัน @Entity, คำสั่ง SQL จะถูกจัดกลุ่มในอินเทอร์เฟสที่มีเอนโนเทชัน @dao, และฐานข้อมูลจะถูกประกอบขึ้นในคลาสนามธรรมที่มี @Database วิธีการนี้แยกโมเดลข้อมูลออกจากตรรกะคำสั่งอย่างเข้มงวด

ตาม Flutter Pulse (2023), Floor ถูกเลือกใน 28% ของโครงการ Flutter ที่ต้องการฐานข้อมูลในเครือง เหตุผลหลักในการเลือกคือความคุ้นเคยกับ SQL (ไม่ต้องเรียนรู้ภาษาคำสั่งใหม่) และการตรวจสอบคำสั่งในขณะแปลงคอม์ไพเลอร์ นอกจากนี้ Floor สร้างโค้ดที่อ่านง่ายและแก้ไขโค้ดได้ง่ายเมื่อเปรียบเทียบกับ ORM ที่มีนามธรรมมากกว่าพร้อม DSL ที่กำหนดเอง ซึ่งช่วยลดอุปสรรคในการเข้าสู่ทีมสำหรับนักพัฒนาใหม่

สถาปัตยกรรม Floor

Floor ประกอบด้วยสามชั้น: Entity (โมเดลตาราง), DAO (อินเทอร์เฟสคำสั่ง) และ Database (จุดเข้า) ตัวสร้างจะสร้างการนำไปใช้ _$_Entity สำหรับการแมปฟีลด์ และ _$_Dao สำหรับการดำเนินการ SQL เมื่อ Entity หรือ DAO เปลี่ยนแปลง, เพียงแค่เริ่ม build_runner ใหม่ — โค้ดจะอัพเดตโดยอัตโนมัติ สำหรับการย้ายข้ามระหว่างเวอร์ชันโครงสร้าง, Floor ใช้หมายเลขเวอร์ชันแบบลำดับ ซึ่งรับประกันความถูกต้องของข้อมูลเมื่ออัพเดตแอพบนอุปกรณ์ของผู้ใช้

Floor ทำงานอย่างไรใน Flutter?

Floor ใช้ SQLite ผ่านแพ็คเกจ sqflite สำหรับบิลด์แพลตฟอร์ม และ sqlite3 สำหรับเดสก์ทอปและเว็บ เมื่อแอพเริ่มทำงาน, Floor จะสร้างหรือเปิดไฟล์ SQLite, ใช้การย้ายข้าม และเตรียมเมธอด DAO สำหรับการดำเนินการคำสั่ง การดำเนินการทั้งหมดจะดำเนินแบบไม่ต้องรอคำตอผ่าน Future และ Stream

การสร้างโค้ดใน Floor ทำงานดังนี้: ตัวแยกอ่านเอนโนเทชันจากไฟล์ต้นฉบับ, สร้าง AST (แบบจำลองโครงสร้างไวยากรณ์) ของโมเดลและคำสั่ง, จากนั้นสร้างไฟล์ Dart ที่มีคำนำหน้า _$ โค้ดที่สร้างขึ้นรวมถึงตัวแมป ResultSet → Entity และในทางกลับ

ความปลอดภัยของเธรด

Floor ทำงานกับ SQLite ในหนึ่ง isolate คำสั่งทั้งหมดจะดำเนินการแบบไม่ต้องรอคำตอบ, แต่การเขียนพร้อมกันจะถูกล็อคในระดับ SQLite สำหรับธุรกรรม, จะใช้เอนโนเทชัน @transaction ซึ่งรับประกันความเป็นเอกภาพของกลุ่มคำสั่งและการย้อนกลับเมื่อเกิดข้อผิดพลาด

Floor vs Drift: เปรียบเทียบ ORM สำหรับ Flutter

ทั้ง Floor และ Drift ล้วนเป็น ORM เทือบ SQLite, แต่แตกต่างกันที่ปรัชญา Floor ใกล้กับ Room ของ Android, Drift ตอบสนองได้มากกว่าด้วย API Stream ในตัวและการคอม์ไพล์คำสั่งผ่านไฟล์ SQL การเลือกระหว่างพวกมันขึ้นอยู่กับประสบการณ์ของทีมและความต้องการการตอบสนอง

ลักษณะFloorDrift
ชนิดคำสั่งสตริง SQL ใน @Queryเมธอด Dart + ไฟล์ sql
การสร้างโค้ดfloor_generator (build_runner)drift_dev (build_runner)
การตอบสนองStream จาก DAOAPI Stream ในตัว + อัพเดตอัตโนมัติ
ความซับซ้อนต่ำ (SQL คุ้นเคย)ปานกลาง (DSL ของตนเอง)
การย้ายข้ามสคริปต์ SQL ด้วยตนอัตโนมัติ + ด้วยตน
ความเข้ากันได้Android, iOS, macOSAndroid, iOS, Web, macOS, Linux

เมื่อไรควรเลือก Floor

Floor เป็นทางเลือกสำหรับทีมที่คุ้นเคยกับ SQL และ Android Room หากนักพัฒนาเคยเขียนคำสั่ง SQL ด้วยตนเองและต้องการเป็นผ้าห่อหุ้มบน SQLite เล็กน้อย — Floor ให้การกำหนดชนิดโดยไม่ต้องเรียนรู้ DSL ใหม่ นอกจากนี้ยังแก้ไขโค้ดได้ง่ายกว่าเพราะโค้ดที่สร้างขึ้นอ่านง่ายและทำนายได้

เมื่อไร Drift ดีกว่า

Drift ให้การตอบสนองที่มีประสิทธิภาพมากขึ้นและรองรับแพลตฟอร์มมากขึ้น หากแอพใช้ Stream อย่างกรมชันเพื่ออัพเดต UI, ต้องการคำสั่งซับซ้อนกับ JOIN และคำสั่งย่อย หรือมุ่งเป้าไปที่เว็บ — Drift เป็นที่เหมาะสม อย่างไรก็ตาม อุปสรรคในการเข้าใช้งานสูงกว่าเนื่องจากต้องเรียนรู้ DSL ของตัวเอง

ตัวอย่างโค้ดกับ Floor

Floor สร้างมาจากเอนโนเทชัน ด้านล่างเป็นตัวอย่างสมบูรณ์ของ Entity, DAO และ Database สำหรับแอพรายการทำงาน หลังจากรัน build_runner คลาสที่สร้างขึ้นพร้อมใช้งาน

การกำหนด Entity และ DAO

คลาส TaskEntity ที่มีเอนโนเทชัน @Entity จะแมปไปที่ตาราง task ฟีลด์ที่มี @primaryKey จะกลายเป็นคีย์หลัก อินเทอร์เฟส TaskDao ประกอบด้วยเมธอดสำหรับการดำเนินการกับตาราง — แต่ละเมธอดจะถูกเอนโนเทชันด้วย @Query, @Insert, @Update หรือ @Delete

dart
@entity
class TaskEntity {
    @PrimaryKey(autoGenerate: true)
    final int id;
    final String title;
    final bool isCompleted;
    final int priority;

    TaskEntity({this.id, required this.title,
        this.isCompleted = false, this.priority = 0});
}

@dao
abstract class TaskDao {
    @Query('SELECT * FROM TaskEntity ORDER BY priority DESC')
    Future<List<TaskEntity>> getAllTasks();

    @Insert
    Future<int> insertTask(TaskEntity task);

    @Update
    Future<void> updateTask(TaskEntity task);

    @Query('SELECT * FROM TaskEntity WHERE isCompleted = :status')
    Stream<List<TaskEntity>> watchTasks(bool status);
}

การเริ่มต้นฐานข้อมูล

คลาสนามธรรมที่มีเอนโนเทชัน @Database เชื่อมต่อ Entity และ DAO เมธอด databaseBuilder สร้างอินสแตนซ์ฐานข้อมูล หลังจากเรียก build, ฐานข้อมูลก็พร้อม: Floor เปิดไฟล์ SQLite, ใช้การย้ายข้าม และส่งคืน DAO สำหรับการทำงาน

dart
@Database(version: 1, entities: [TaskEntity])
abstract class AppDatabase extends FloorDatabase {
    TaskDao get taskDao;
}

// การใช้งาน
final database = await $FloorAppDatabase.databaseBuilder('app.db').build();
final taskDao = database.taskDao;
final tasks = await taskDao.getAllTasks();

คำสั่งแบบตอบสนองผ่าน Stream

Floor รองรับการส่งคืน Stream จากเมธอด DAO เมื่อมีการเปลี่ยนแปลงในตาราง, Stream จะส่งรายการใหม่ ซึ่งผนวการกับ StreamBuilder ใน Flutter — UI จะอัพเดตโดยอัตโนมัติเมื่อมีการเพิ่ม, แก้ไข หรือลบรือง

dart
@Query('SELECT * FROM TaskEntity ORDER BY priority DESC')
Stream<List<TaskEntity>> watchAllTasks();

// ใน Flutter widget
StreamBuilder<List<TaskEntity>>(
    stream: taskDao.watchAllTasks(),
    builder: (context, snapshot) {
        final tasks = snapshot.data ?? [];
        return ListView.builder(
            itemCount: tasks.length,
            itemBuilder: (_, i) => TaskTile(tasks[i]),
        );
    },
)

การย้ายข้ามและการกำกับเวอร์ชันใน Floor

Floor รองรับการกำกับเวอร์ชันของฐานข้อมูลผ่านพารามิเตอร์ version ในเอนโนเทชัน @Database เมื่อ Entity เปลี่ยนแปลง (เพิ่มหรือลบฟีลด์), คุณต้องเพิ่มเวอร์ชันและเพิ่มการย้ายข้าม การย้ายข้ามคือฟังก์ชัน Dart ที่รับธุรกรรมและดำเนินการคำสั่ง SQL ALTER TABLE

ตัวอย่างการย้ายข้าม

สมมติว่าในเวอร์ชัน 2 เราเพิ่มฟีลด์ dueDate ใน TaskEntity การย้ายข้ามจะดำเนินการผ่านคำสั่ง SQL ALTER TABLE หากไม่ได้ระบุการย้ายข้าม, Floor จะเรียก MigrationStrategy ซึ่งคุณสามารถตั้งค่า fallback (เช่น, สร้างตารางใหม่โดยสูญเสียข้อมูล)

การทดสอบคำสั่ง Floor

Floor ไม่มีเฟรมเวิร์กจำลองในตัว, แต่ฐานข้อมูลสามารถแทนที่ได้ง่ายในการทดสอบ สร้าง inMemoryDatabaseBuilder — มันสร้างฐานข้อมูล SQLite ในหน่วยความจำที่มีโครงสร้างเหมือนกับการผลิต หลังจากแต่ละการทดสอบ, ให้ล้างข้อมูลผ่าน deleteDatabase เพื่อแยกสถานการณ์การทดสอบ

ธุรกรรมและการดำเนินการแบบชุดใน Floor

Floor รองรับธุรกรรมผ่านเอนโนเทชัน @transaction บนเมธอด DAO ภายในธุรกรรม, หลายคำสั่งจะถูกดำเนินการตามลำดับโดยมีการรับประกันการย้อนกลับเมื่อเกิดข้อผิดพลาด การแทรกข้อมูลแบบชุดผ่าน @Insert กัพารามิเตอร์ List จะเพิ่มประสิทธิภาพของการแทรกหลายรีคอร์ดในการเรียกเดียว — รวดเร็วกว่าการแทรกทีละรีคอร์ดในลูปหลายเท่า สำหรับการทำงานจำนวนมาก, ให้ใช้การแทรกแบบชุด 100–200 รีคอร์ด: นี่คือความสมดุลระหว่างความเร็วในการดำเนินการและการใช้ RAM บนอุปกรณ์มือถือที่มีทรัพยากรจำกัด

dart
final migration1to2 = Migration(1, 2, (database) async {
    await database.execute(
        'ALTER TABLE TaskEntity ADD COLUMN dueDate TEXT'
    );
});

final database = await $FloorAppDatabase.databaseBuilder('app.db')
    .addMigrations([migration1to2])
    .build();

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

Floor แตกต่างจาก sqflite ดิบอย่างไร?

sqflite ต้องการเขียนคำสั่ง SQL ด้วยตนและการแมป ResultSet ไปเป็นอ็อบเจกต์ Floor สร้างโค้ดนี้โดยอัตโนมัติ: คุณอธิบาย Entity และ DAO, และเมธอดที่ได้รับการกำหนดชนิดจะส่งคืนอ็อบเจกต์ Dart ที่พร้อมใช้งาน Floor ยังตรวจสอบคำสั่ง SQL ในขณะแปลงคอม์ไพเลอร์ผ่านเอนโนเทชัน

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

Floor ไม่มีเอนโนเทชันในตัวสำหรับความสัมพันธ์ (ForeignKey, @Relation) เหมือน Room ความสัมพันธ์จะถูกนำไปใช้ผ่านคำสั่ง SQL JOIN ด้วยตนใน @Query สำหรับโครงสร้างความสัมพันธ์ที่ซับซ้อน, พิจารณา Drift ที่มีการรองรับความสัมพันธ์ในตัว

จะแก้ไขโค้ดคำสั่ง SQL ของ Floor ได้อย่างไร?

Floor อนุญาตให้เปิดใช้งาน callback เมื่อสร้าง DatabaseBuilder — โดยจะได้รับอินสแตนซ์ของ sqflite.Database ที่คุณสามารถแนบ logger ได้ อีกทางเลือก, ใช้ floor_doctor เพื่อเบิ่งเห็นโครงสร้างและข้อมูลในโหมด dev

สามารถใช้ Floor สำหรับการสร้างเว็บได้หรือไม่?

Floor ใช้ sqflite ซึ่งไม่ทำงานในสภาพแวดล้อมเว็บ สำหรับเว็บ, จำเป็นต้องมีการสร้างแยกด้วย sqlite3 ผ่าน WASM ในเวอร์ชันปัจจุบัน, Floor รองรับ Android, iOS และ macOS อย่างเป็นทางการ สำหรับเว็บ, ใช้ Drift กับตัวปรับ sqlite3

แคชคำสั่งใน Floor ทำงานอย่างไร?

Floor ไม่มีแคชในตัว — แต่ละคำสั่งจะถูกดำเนินการบน SQLite สำหรับการแคชคำสั่งที่ทำซ้ำ, ใช้ชั้น Repository ที่มีแคชในหน่วยความจำ (เช่น, dart_cache) Floor สร้างเฉพาะโค้ดสำหรับการทำงานกับ SQLite โดยไม่เพิ่มโอเวอร์เฮดใดๆ

สรุป

  • Floor — ORM เทือบ SQLite พร้อมการสร้างโค้ด Entity, DAO และ Database ผ่านเอนโนเทชัน
  • ความปลอดภัยของชนิด — คำสั่ง SQL ถูกตรวจสอบในขณะแปลงคอม์ไพเลอร์ผ่านเอนโนเทชัน @Query
  • แบบ DAO — คำสั่ง SQL ถูกห่อหุ้มในเมธอด Dart, แยกโมเดลออกจากตรรกะ
  • การย้ายข้าม — การกำกับเวอร์ชันโครงสร้างผ่าน Migration ด้วย ALTER TABLE ด้วยตน
  • การตอบสนอง — Stream จาก DAO สำหรับการอัพเดต UI โดยอัตโนมัติเมื่อมีการเปลี่ยนแปลง
  • ข้อจำกัด — ไม่มีความสัมพันธ์ในตัว, ไม่รองรับการสร้างเว็บ
  • คำแนะนำ — เลือก Floor สำหรับโครงการ Flutter ที่ทีมคุ้นเคยกับ SQL และวิธีการของ Room

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

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

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

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