Lưu trữ dữ liệu với SQLite

Khóa học lập trình Android cơ bản

5.0 (1 đánh giá)
Tạo bởi Kteam Cập nhật lần cuối 17:20 14-08-2020 72.406 lượt xem 0 bình luận
Tác giả/Dịch giả: Kteam
Học nhanh

Danh sách bài học

Lưu trữ dữ liệu với SQLite

Dẫn nhập

Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về CÁCH LƯU TRỮ DỮ LIỆU ĐƠN GIẢN DẠNG KEY - VALUE. Cách này phù hợp khi cần lưu dữ liệu nhỏ, ví dụ như thông tin đăng nhập, cookie, hoặc một số tinh chỉnh trong ứng dụng.

Tuy nhiên với những ứng dụng cần sử dụng khối lượng dữ liệu lớn hơn, chúng ta sẽ cần cách lưu trữ khác. Và đặc biệt là với dạng dữ liệu có cấu trúc, cần truy cập sau này theo dạng truy vấn thì không gì thích hợp hơn cơ sở dữ liệu (Database).

Thật ngon lành là Android (và cả iOS) có hỗ trợ SQLite – một hệ cơ sở dữ liệu nguồn mở. Bài học này chúng ta sẽ cùng tìm hiểu về nó.


Nội dung

Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:

Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:

  • SQLite là gì.
  • Những kiểu dữ liệu được hỗ trợ trong SQLite.
  • Viết một ứng dụng nhỏ để thêm / xoá tên trong SQLite.

SQLite là…

  • Một hệ cơ sở dữ liệu nguồn mở.
  • Hỗ trợ cú pháp y như SQL.
  • Là dạng cơ sở dữ liệu quan hệ (standard relational database).
  • Được tích hợp vào mọi thiết bị Android, không cần cài đặt và tiến hành cấu hình quản trị.
  • Bạn chỉ cần viết câu lệnh tạo bảng và cập nhật bảng, còn lại việc quản lý Android sẽ do hệ điều hành phụ trách.

SQLite hỗ trợ các kiểu dữ liệu

  • TEXT (văn bản thường).
  • INTEGER (số nguyên, nhưng tương đương với kiểu Long trong Java).
  • REAL (số thực, tương đương với Double trong Java).

Ngoài ra SQLite cũng có thể lưu được cả hình ảnh nếu chuyển đổi dữ liệu sang dạng Base64. Lưu ý là với cách này thì dung lượng dữ liệu sẽ bị dội lên.

Tất cả các loại dữ liệu khác đều phải chuyển đổi sang 3 dạng trên để có thể chèn vào trong bảng của SQLite. Tuy nhiên SQLite không kiểm tra dữ liệu. Tức là bạn có thể chèn dữ liệu TEXT vào column dữ liệu dạng INTEGER.

Việc truy cập vào SQLite sẽ dẫn đến truy cập vào file hệ thống. Do đó thời gian thực thi sẽ lâu hơn so với các thao tác khác. Cũng vì thế mà việc truy vấn SQLite khuyến cáo nên thực hiện bất đồng bộ (Asynchronous).

Nếu như ứng dụng của bạn tạo ra bảng, mặc định nó sẽ nằm ở:

DATA/data/TÊN_APP/databases/TÊN_FILE.DB

Thật ra đường dẫn trên được cấu thành từ những quy định sau:

  • DATA: Đường dẫn này được tạo nên từ kết quả trả về của hàm Environment.getDataDirectory()
  • TÊN_APP: Tên ứng dụng.
  • TÊN_FILE: Tên của bảng, lúc tạo bảng bạn đặt thế nào thì nó ra thế này.

Kiến trúc của SQLite

Package

Package android.database cung cấp tất cả các lớp sử dụng để thao tác với cơ sở dữ liệu.

Package android.database.sqlite cung cấp các lớp thao tác với SQLite nói riêng.


Tạo và upgrade cơ sở dữ liệu với SQLiteOpenHelper

Để tạo và upgrade cơ sở dữ liệu trong ứng dụng Android, các bạn cần kế thừa từ lớp SQLiteOpenHelper, gọi ra hàm super() để lấy các method cần thiết từ lớp cha, sau đó chỉ định tên database và phiên bản database.

Trong lớp đã tạo chúng ta phải override 2 hàm sau:

  • onCreate(): Gọi khi database được truy cập, nhưng chưa được tạo xong.
  • onUpgrade(): Gọi ra khi phiên bản database được nâng lên. Chú ý là phiên bản database chỉ có tăng chứ không giảm.

Cả 2 phương thức này đều nhận một đối tượng SQLiteDatabase làm tham số đầu vào, cũng là đối tượng Java đại diện cho cơ sở dữ liệu.

Lớp SQLiteOpenHelper cung cấp 2 phương thức để lấy database:

  • getReadableDatabase(): Lấy ra database dạng chỉ đọc.
  • getWriteableDatabase(): Lấy ra database dạng ghi được.

Các bảng cơ sở dữ liệu đều sử dụng một khoá chính là _id. Có nhiều thao tác cơ sở dữ liệu chính được dựa trên cái khoá này.

Chú ý: Do _id là kiểu INTEGER trong bảng SQLite, mà kiểu này lại tương ứng với Long trong Java, các bạn chú ý khi sử dụng.

Một lời khuyên được đưa ra ở đây là mỗi model nên tương ứng với 1 bảng, mỗi bảng có phương thức onCreate onUpgrade riêng, sau này sẽ dễ đọc hơn.


SQLiteDatabase

SQLiteDatabase là lớp cơ bản dùng để làm việc với SQLite trong Android, và nó cũng cung cấp phương thức để làm việc với database thông thường như sửa /xoá /mở /đóng database. Cụ thể là những phương thức sau:

  • insert()
  • update()
  • delete()

Thêm vào đó, nó cũng cung cấp phương thức execSQL, cho phép thực thi trực tiếp câu lệnh truy vấn SQL.

Dữ liệu trong bảng thường được tham chiếu dạng key-value, vậy thì nó được thể hiện trong Java thế nào?

Câu trả lời là ContentValues. “key” thể hiện đặc tính giá trị và “value” thể hiện giá trị tương ứng trong mỗi bản ghi.

- “Dài dòng quá” – một bạn lười đọc cho biết.

Vậy thì hiểu ngắn gọn: Nó dùng để chèn hoặc cập nhật bản ghi trong Database là đủ rồi.

Các câu truy vấn có thể được thực thi qua 2 dạng, 2 dạng này đều trả về “con trỏ” (cursor), từ con trỏ này chúng ta mới lấy ra dữ liệu thêm:

  • rawQuery(): Chấp nhận lệnh truy vấn SQL trực tiếp.
  • query(): Phương thức này thì… không hẳn là dễ hơn nhưng an toàn hơn, nó cung cấp giao diện (interface) để lập trình viên viết lệnh truy vấn thuần với Java hơn một chút.

Ngoài ra chúng ta còn có lớp SQLQueryBuilder, dùng để viết câu lệnh truy vấn SQL thuận tiện hơn nữa.


Ví dụ: rawQuery()

Cursor cursor = getReadableDatabase().

        rawQuery("select * from user where _id = ?", new String[] { id });

Câu lệnh trên sử dụng để chọn tất cả những bản ghi trong bảng “user”.


Ví dụ: query()

Chúng ta có truy vấn bằng phương thức query()

return database.query(DATABASE_TABLE,

        new String[] { KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY, KEY_DESCRIPTION },

        null, null, null, null, null);

Câu lệnh trên sẽ chọn tất cả các bản ghi chứa các cột có key là KEY_ROWID, KEY_CATEGORY,…

Bảng sau mô tả các tham số đầu vào của phương thức query()

Lưu trữ dữ liệu với SQLite


Một số lưu ý thêm:

Với query() thì khi dùng tham số whereClause, chúng ta không cần thêm chữ “WHERE” vào. Ví dụ: Chỉ cần như thế này là đủ: “_id=69 and summary=?

  • Nếu có giá trị tạm giữ (chỗ dấu ? ý) thì các bạn thêm chúng vào ở selectionArgs.

Mỗi truy vấn trên đều trả về Cursor. Cursor ở đây tức là con trỏ, nó đại diện cho tập các giá trị đã truy vấn được, và bản thân nó sẽ “trỏ” vào một giá trị trong tập dữ liệu trả về. Tức là sao? Với cách này Android sẽ tiết kiệm được bộ nhớ, không cần phải xử lý ồ ạt cả đống dữ liệu trả về nữa.

  • Để lấy tổng số dữ liệu trả về, ta dùng getCount().
  • Để nhảy con trỏ tới tiếp theo hoặc trên cùng, ta dùng moveToNext() moveToFirst().
  • Để kiểm tra xem con trỏ đã trỏ đến kết quả cuối cùng chưa, ta dùng hàm isAfterLast().
  • Cursor cung cấp các hàm get*(), ví dụ: getLong(columnIndex), getString(columnIndex),… trong đó columnIndex là số của cột mà bạn đang truy cập.

Kết luận

Qua bài này chúng ta đã nắm được SQLite là gì, các lớp làm việc với SQLite và các hàm truy vấn SQLite.

Bài sau, chúng ta sẽ làm một ứng dụng nhỏ để thêm và xoá danh sách trong SQLite, cũng như làm quen với KHÁI NIỆM ORM (Object Relational Mapping) 

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Tải xuống

Tài liệu

Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Lưu trữ dữ liệu với SQLite dưới dạng file PDF trong link bên dưới.

Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com

Đừng quên likeshare để ủng hộ Kteam và tác giả nhé!


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Khóa học

Khóa học lập trình Android cơ bản

Serial tutorial hướng dẫn lập trình Android cơ bản

Đánh giá

Vo Tan Duc đã đánh giá 11:23 15-02-2024

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Không có video.