[FLUTTER] Tìm hiểu về cách sử dụng SQLite trong Flutter

Để lưu những dữ liệu theo dạng bảng dễ dàng cho việc truy vấn và thay đổi, chúng ta cần sử dụng SQLite

I. Khái quát về Sqlite trong Flutter

Trong Flutter chúng ta sử dụng thư viện sqflite, thư viện này sẽ hỗ trợ chúng ta:

  • Sử dụng trên đa nền tảng Android, iOS, MacOS.
  • Hỗ trợ transactions và batches.
  • Tự động quản lý phiên bản (version) trong khi mở.
  • Hỗ trợ các câu lệnh truy vấn CRUD (Create – Read – Update – Delete) đầy đủ.
  • Thực hiện các xử lý trên background của iOS và Android.

II. Cách sử dụng Sqlite trong Flutter

1. Thêm thư viện

1.1. Thêm thư viện sqflite path (dùng để xác định vị trí lưu database trong bộ nhớ) vào phần dependencies trong file pubspec.yaml

2. Cài đặt thư viện

2.1. Đầu tiên chúng ta cần tạo một class model Student, đây sẽ là dữ liệu chúng ta dùng trong quá trình lưu trữ.

class Student {
  int id;
  String name;
  int grade;

  Student({required this.id, required this.name, required this.grade});
}

Nếu bạn chưa biết rõ về Sql cũng như các câu lệnh của chúng, hãy tìm hiểu về chúng trước khi tiếp tục: SQL Introduction (w3schools.com)

2.2. Tiếp theo chúng ta khởi tạo database

class StudentDatabase {
  static Database? _database;

  static Future<Database> getInstance() async {
    _database ??= await openDatabase(

        /// use join to create path for db, then the path will be path/student.db
        join(await getDatabasesPath(), "student.db"),

        /// This function will be called in the first time database is created
        onCreate: (db, version) {
      return db.execute(
          "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT, grade INTEGER)");
    },

        /// This version will use when you want to upgrade or downgrade the database
        version: 1,
        singleInstance: true);
    return _database!;
  }
}
  • Hàm onCreate() được gọi tại lần đầu mà database được khởi tạo
  • Version chính là phiên bản của database, nếu bạn muốn thay đổi cấu trúc của database thì chúng ta phải thay đổi version.

Tiếp theo ta thêm các hàm phục vụ cho việc chuyển đổi dữ liệu khi muốn thêm vào database cũng như lấy dữ liệu ra từ database

class Student{
...

Map<String, dynamic> toMap() => {'id': id, 'name': name, 'grade': grade};

factory Student.fromMap(Map<String, dynamic> map) {
  return Student(id: map['id'], name: map['name'], grade: map['grade']);
}
...
}

Ở đây mình có viết thành một project CRUD, với các phân tần giữa data và UI rõ ràng, để có thể hiểu hơn về project này hãy đọc đến cuối bài viết.

2.3. Thêm một trường dữ liệu vào bảng

Future<DataResult> insertStudent(Student student, String tableName) async {
    try{
      Database db = await StudentDatabase.getInstance();
      int lastInsertedRow = await db.insert(tableName, student.toMap(),
          conflictAlgorithm: ConflictAlgorithm.replace);
      return DataResult.success(lastInsertedRow);
    }catch(ex){
      return DataResult.failure(DatabaseFailure(ex.toString()));
    }
  }
  • Hàm insert() có hai tham số truyền vào là tên của bảng và dữ liệu chúng ta muốn thêm vào bảng, dữ liệu này đã được chuyển thành một map để có thể thực hiện thêm vào database.
  • Tham số conflictAlgorithm: được sử dụng để xác định các xử lý khi có sự trùng lặp dữ liệu xảy ra, ở đây tham số này có giá trị là ConflictAlgorithm.replace có nghĩa là nếu trùng primary key thì giá trị cũ sẽ được thay thế bằng giá trị mới.
  • Nếu hàm insert thực hiện thành công sẽ trả về id của hàng vừa được thêm.
  • Nếu không thành công sẽ trả về giá trị 0.

2.4. Lấy thông tin của tất cả các trường

Trong Android Studio có một công cụ hỗ trợ chúng ta xem được các cơ sở dữ liệu đang có trong app, đó chính là App Inspection

Tại đây chúng ta có thể thấy được bảng “student” đã được thêm 33 trường dữ liệu, vậy bây giờ chúng ta muốn lấy tất cả những dữ liệu này ra thì phải làm thế nào?

Future<DataResult> getAllStudent() async{
    try{
      Database db = await StudentDatabase.getInstance();
      final List<Map<String,dynamic>> maps = await db.query("student");
      List<Student> students = maps.map((e) => Student.fromMap(e)).toList();
      return DataResult.success(students);
    }catch(ex){
      return DataResult.failure(DatabaseFailure(ex.toString()));
    }
  }

Chúng ta chỉ cần sử dụng hàm query, truyền vào tham số là bảng mà chúng ta cần lấy dữ liệu.

  • Dữ liệu trả về sẽ ở dạng List<Map<String,dynamic>>, vì vậy chúng ta cần chuyển đổi chúng sang dạng của lớp Student sử dụng hàm fromMap() đã được thêm trong class Student

2.5. Thay đổi thông tin của một trường.

Future<DataResult> updateStudent(Student student) async{
    try{
      Database db = await StudentDatabase.getInstance();
      int numberOfChanges = await db.update("student", student.toMap(),where: "id = ?",whereArgs: [student.id]);
      return DataResult.success(numberOfChanges);
    }catch(ex){
      return DataResult.failure(DatabaseFailure(ex.toString()));
    }
  }

Để thực hiện được việc thay đổi dữ liệu của một trường chúng ta cần sử dụng hàm update()

  • Các tham số truyền vào gồm có tên bảng, dữ liệu thay đổi (được chuyển sang map), điều kiện thay đổi và tham số cho điều kiện đó.
  • Có thể thấy phần thay đổi dữ liệu này khá giống với phần thêm dữ liệu, chỉ khác chúng ta có thêm hai tham số khá quan trọng là “where” và “whereArgs”.
  • Giá trị trả về của hàm update() là số lượng thay đổi đã diễn ra.

2.6. Xóa thông tin của một trường

Future<DataResult> deleteStudent(int id) async{
    try{
      Database db = await StudentDatabase.getInstance();
      int numberOfRowEffected = await db.delete("student",where: "id = ?",whereArgs: [id]);
      return DataResult.success(numberOfRowEffected);
    }catch(ex){
      return DataResult.failure(DatabaseFailure(ex.toString()));
    }
  }

Để thực hiện việc xóa dữ liệu chúng ta sẽ cần dùng đến hàm delete()

  • Gần giống với hàm update chúng ta cũng cần có hai tham số “where” và “whereArgs”
  • Giá trị trả về sẽ là hàng bị thay đổi giá trị.

III. Tổng kết

Phần Sql này khá là khó và khô khan đối với những người mới học, mới tiếp cận, vì vậy mọi người cần luyện tập thêm để trở nên master phần này nhé.

Link github của project mình tự làm cho mọi người tham khảo: lamdev99/sqflite_crud (github.com)

Tài liệu tham khảo:

Author: LamNT59

1 comment

Nam April 6, 2022 - 3:22 PM

bài viết rất hữu ích

Reply

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

You may also like

%d bloggers like this: