Floor — Flutter-এর জন্য ORM (Object-Relational Mapping), যা SQLite-এর উপরে একটি টাইপযুক্ত স্তর প্রদান করে। র SQLite কোয়েরির বিপরীতে, Floor অ্যানোটেটেড Dart মডেল থেকে DAO ক্লাস জেনারেট করে। Pub.dev, 2024 অনুসারে, Floor 3500-এর বেশি Flutter প্রজেক্টে ব্যবহৃত হয় এবং drift ও hive-এর পাশাপাশি লোকাল ডাটা স্টোরেজের জন্য শীর্ষ তিনটি জনপ্রিয় ORM সমাধানের মধ্যে একটি।
মূল বিষয়
Floor হল SQLite-এর উপরে নির্মিত Flutter এবং Dart-এর জন্য একটি ORM লাইব্রেরি। এটি এনটিটি (Entity), Data Access Objects (DAO) এবং ডাটাবেস (Database) বর্ণনা করতে অ্যানোটেশন ব্যবহার করে। কোড জেনারেশন build_runner এবং floor_generator-এর মাধ্যমে করা হয় — কম্পাইলার DAO ইমপ্লিমেন্টেশন এবং একটি ব্যবস্থাপক ডাটাবেস ক্লাস তৈরি করে। র sqflite-এর বিপরীতে, Floor টাইপ রিফ্লেকশনের মাধ্যমে কলামগুলোকে Entity ফিল্ডে স্বয়ংক্রিয়ভাবে ম্যাপ করে ResultSet থেকে Dart অবজেক্টে ম্যানুয়াল রূপান্তরের প্রয়োজন সম্পূর্ণরূপে দূর করে।
Floor Android ডেভেলপারদের Room থেকে পরিচিত Repository + DAO প্যাটার্ন অনুসরণ করে। প্রতিটি টেবিল @Entity অ্যানোটেশনযুক্ত একটি Dart ক্লাস দ্বারা উপস্থাপিত হয়, SQL কোয়েরিগুলো @dao অ্যানোটেশনযুক্ত ইন্টারফেসে গ্রুপ করা হয় এবং ডাটাবেস @Database অ্যানোটেশনযুক্ত একটি অ্যাবস্ট্রাক্ট ক্লাসে একত্রিত করা হয়। এই পদ্ধতি ডাটা মডেলকে কোয়েরি লজিক থেকে কঠোরভাবে পৃথক করে।
Flutter Pulse (2023) অনুসারে, 28% Flutter প্রজেক্টে Floor বেছে নেওয়া হয় যেখানে লোকাল ডাটাবেস প্রয়োজন। এটি বেছে নেওয়ার প্রধান কারণ হল SQL-এর সাথে পরিচিতি (নতুন কোয়েরি ভাষা শেখার প্রয়োজন নেই) এবং কম্পাইল-টাইম কোয়েরি পরীক্ষা। অতিরিক্তভাবে, Floor পঠনযোগ্য কোড জেনারেট করে যা কাস্টম DSL-সহ আরও অ্যাবস্ট্রাক্ট ORM-এর তুলনায় ডিবাগ করা সহজ, যা টিমের নতুন ডেভেলপারদের জন্য প্রবেশের বাধা কমায়।
Floor তিনটি স্তর নিয়ে গঠিত: Entity (টেবিল মডেল), DAO (কোয়েরি ইন্টারফেস) এবং Database (প্রবেশ বিন্দু)। জেনারেটর ফিল্ড ম্যাপিংয়ের জন্য _$_Entity ইমপ্লিমেন্টেশন এবং SQL নির্বাহের জন্য _$_Dao তৈরি করে। যখন Entity বা DAO পরিবর্তিত হয়, build_runner পুনরায় চালানোই যথেষ্ট — কোড স্বয়ংক্রিয়ভাবে আপডেট হয়। স্কিমা ভার্সনের মধ্যে মাইগ্রেশনের জন্য, Floor ক্রমিক ভার্সন নম্বর ব্যবহার করে, যা ব্যবহারকারীদের ডিভাইসে অ্যাপ আপডেট করার সময় ডাটা অখণ্ডতা নিশ্চিত করে।
Floor প্ল্যাটফর্ম বিল্ডের জন্য sqflite প্যাকেজ এবং ডেস্কটপ ও ওয়েবের জন্য sqlite3-এর মাধ্যমে SQLite ব্যবহার করে। অ্যাপ শুরু হলে, Floor SQLite ফাইল তৈরি বা খোলে, মাইগ্রেশন প্রয়োগ করে এবং কোয়েরি নির্বাহের জন্য DAO মেথড প্রস্তুত করে। সমস্ত অপারেশন Future এবং Stream-এর মাধ্যমে অ্যাসিঙ্ক্রোনাসভাবে সম্পাদিত হয়।
Floor-এ কোড জেনারেশন এভাবে কাজ করে: পার্সার সোর্স ফাইল থেকে অ্যানোটেশন পড়ে, মডেল এবং কোয়েরির AST (Abstract Syntax Tree) তৈরি করে, তারপর _$ উপসর্গসহ Dart ফাইল জেনারেট করে। জেনারেটেড কোডে ResultSet → Entity ম্যাপার এবং এর বিপরীত অন্তর্ভুক্ত।
Floor একটি একক isolate-এ SQLite-এর সাথে কাজ করে। সমস্ত কোয়েরি অ্যাসিঙ্ক্রোনাসভাবে নির্বাহিত হয়, কিন্তু সমবর্তী লেখা SQLite স্তরে লক করা হয়। লেনদেনের জন্য, @transaction অ্যানোটেশন ব্যবহার করা হয়, যা কোয়েরির গ্রুপের পারমাণবিকতা এবং ত্রুটিতে রোলব্যাক নিশ্চিত করে।
Floor এবং Drift উভয়ই SQLite-এর উপরে ORM, কিন্তু তারা দর্শনে ভিন্ন। Floor Android-এর Room-এর কাছাকাছি, Drift বিল্ট-ইন Stream API এবং SQL ফাইলের মাধ্যমে কোয়েরি কম্পাইলেশনসহ আরও রিঅ্যাক্টিভ। তাদের মধ্যে পছন্দ টিমের অভিজ্ঞতা এবং প্রয়োজনীয় রিঅ্যাক্টিভিটির উপর নির্ভর করে।
| বৈশিষ্ট্য | Floor | Drift |
|---|---|---|
| কোয়েরির ধরন | @Query-তে SQL স্ট্রিং | Dart মেথড + sql ফাইল |
| কোড জেনারেশন | floor_generator (build_runner) | drift_dev (build_runner) |
| রিঅ্যাক্টিভিটি | DAO থেকে Stream | বিল্ট-ইন Stream API + অটো-আপডেটিং |
| জটিলতা | কম (পরিচিত SQL) | মধ্যম (নিজস্ব DSL) |
| মাইগ্রেশন | ম্যানুয়াল SQL স্ক্রিপ্ট | স্বয়ংক্রিয় + ম্যানুয়াল |
| সামঞ্জস্যতা | Android, iOS, macOS | Android, iOS, Web, macOS, Linux |
Floor হল সেই টিমের জন্য পছন্দ যারা ইতিমধ্যে SQL এবং Android Room-এর সাথে পরিচিত। যদি ডেভেলপাররা ম্যানুয়ালি SQL কোয়েরি লিখতে অভ্যস্ত হন এবং SQLite-এর উপরে ন্যূনতম আবরণ চান — Floor নতুন DSL না শিখেই টাইপিং প্রদান করে। এটি ডিবাগ করাও সহজ কারণ জেনারেটেড কোড পঠনযোগ্য এবং অনুমানযোগ্য।
Drift আরও শক্তিশালী রিঅ্যাক্টিভিটি প্রদান করে এবং আরও প্ল্যাটফর্ম সমর্থন করে। যদি অ্যাপ UI আপডেটের জন্য Stream সক্রিয়ভাবে ব্যবহার করে, JOIN এবং সাবকোয়েরিসহ জটিল কোয়েরির প্রয়োজন হয় বা ওয়েবকে লক্ষ্য করে — Drift পছন্দনীয়। তবে, এর নিজস্ব DSL শেখার প্রয়োজনীয়তার কারণে এর প্রবেশের বাধা বেশি।
Floor অ্যানোটেশনের চারপাশে নির্মিত। নিচে একটি টাস্ক লিস্ট অ্যাপের জন্য Entity, DAO এবং Database-এর সম্পূর্ণ উদাহরণ দেওয়া হল। build_runner চালানোর পর, জেনারেটেড ক্লাস ব্যবহারের জন্য প্রস্তুত।
TaskEntity ক্লাস @Entity অ্যানোটেশনসহ task টেবিলে ম্যাপ হয়। @primaryKey-যুক্ত ফিল্ডটি প্রাথমিক কী হয়ে যায়। TaskDao ইন্টারফেসে টেবিল অপারেশনের জন্য মেথড রয়েছে — প্রতিটি মেথড @Query, @Insert, @Update বা @Delete দিয়ে অ্যানোটেটেড।
@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 ফিরিয়ে দেয়।
@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();
Floor DAO মেথড থেকে Stream ফেরত দেওয়া সমর্থন করে। টেবিলে যেকোনো পরিবর্তনে, Stream একটি নতুন তালিকা নির্গত করে। এটি Flutter-এ StreamBuilder-এর সাথে সংহত হয় — রেকর্ড যোগ, পরিবর্তন বা মুছে ফেললে UI স্বয়ংক্রিয়ভাবে আপডেট হয়।
@Query('SELECT * FROM TaskEntity ORDER BY priority DESC')
Stream<List<TaskEntity>> watchAllTasks();
// Flutter উইজেটে
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 @Database অ্যানোটেশনে version প্যারামিটারের মাধ্যমে ডাটাবেস ভার্সনিং সমর্থন করে। যখন Entity পরিবর্তিত হয় (ফিল্ড যোগ বা অপসারণ), তখন ভার্সন বাড়ানো এবং মাইগ্রেশন যোগ করা প্রয়োজন। মাইগ্রেশন একটি Dart ফাংশন যা একটি লেনদেন গ্রহণ করে এবং ALTER TABLE SQL কোয়েরি নির্বাহ করে।
ধরুন ভার্সন 2-এ আমরা TaskEntity-তে dueDate ফিল্ড যোগ করেছি। মাইগ্রেশন ALTER TABLE SQL কোয়েরির মাধ্যমে করা হয়। যদি মাইগ্রেশন নির্দিষ্ট না করা হয়, Floor MigrationStrategy কল করে যেখানে আপনি fallback সেট করতে পারেন (যেমন, ডাটা হারিয়ে টেবিল পুনরায় তৈরি করা)।
Floor বিল্ট-ইন মক ফ্রেমওয়ার্ক প্রদান করে না, কিন্তু ডাটাবেস পরীক্ষায় সহজেই প্রতিস্থাপন করা যায়। একটি inMemoryDatabaseBuilder তৈরি করুন — এটি স্কিমায় প্রোডাকশনের মতোই মেমরিতে SQLite ডাটাবেস তৈরি করে। প্রতিটি পরীক্ষার পর, পরীক্ষার পরিস্থিতি আলাদা করতে deleteDatabase-এর মাধ্যমে ডাটা পরিষ্কার করুন।
Floor DAO মেথডে @transaction অ্যানোটেশনের মাধ্যমে লেনদেন সমর্থন করে। একটি লেনদেনের ভিতরে, ত্রুটিতে রোলব্যাক গ্যারান্টিসহ একাধিক কোয়েরি ক্রমিকভাবে নির্বাহিত হয়। List
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();
সচরাচর জিজ্ঞাসা
sqflite-তে ম্যানুয়ালি SQL কোয়েরি লেখা এবং ResultSet-কে অবজেক্টে ম্যাপ করার প্রয়োজন হয়। Floor এই কোড স্বয়ংক্রিয়ভাবে জেনারেট করে: আপনি Entity এবং DAO বর্ণনা করেন, এবং টাইপযুক্ত মেথড ব্যবহারের জন্য প্রস্তুত Dart অবজেক্ট ফেরত দেয়। Floor অ্যানোটেশনের মাধ্যমে কম্পাইল টাইমে SQL কোয়েরিও পরীক্ষা করে।
Floor-এ Room-এর মতো সম্পর্কের জন্য বিল্ট-ইন অ্যানোটেশন (ForeignKey, @Relation) নেই। সম্পর্ক @Query-তে ম্যানুয়াল SQL JOIN কোয়েরির মাধ্যমে বাস্তবায়িত হয়। জটিল রিলেশনাল স্কিমার জন্য, বিল্ট-ইন সম্পর্ক সমর্থনসহ Drift বিবেচনা করুন।
Floor DatabaseBuilder তৈরি করার সময় callback সক্রিয় করার অনুমতি দেয় — এটি sqflite.Database-এর একটি ইনস্ট্যান্স গ্রহণ করে যাতে আপনি লগার সংযুক্ত করতে পারেন। বিকল্পভাবে, ডেভ মোডে স্কিমা এবং ডাটা ভিজ্যুয়ালাইজ করতে floor_doctor ব্যবহার করুন।
Floor sqflite ব্যবহার করে, যা ওয়েব পরিবেশে কাজ করে না। ওয়েবের জন্য, WASM-এর মাধ্যমে sqlite3-সহ পৃথক বিল্ড প্রয়োজন। বর্তমান সংস্করণে, Floor আনুষ্ঠানিকভাবে Android, iOS এবং macOS সমর্থন করে। ওয়েবের জন্য, sqlite3 অ্যাডাপ্টারসহ Drift ব্যবহার করুন।
Floor-এ বিল্ট-ইন ক্যাশিং নেই — প্রতিটি কোয়েরি SQLite-এ নির্বাহিত হয়। পুনরাবৃত্ত কোয়েরি ক্যাশ করার জন্য, ইন-মেমরি ক্যাশ (যেমন, dart_cache)সহ Repository স্তর ব্যবহার করুন। Floor কেবল SQLite-এর সাথে কাজ করার জন্য কোড জেনারেট করে, তার উপরে কোনো অতিরিক্ত বোঝা যোগ না করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন