Bài 21: SQLite trong Android - Lập trình Android cơ bản

Đăng bởi: Admin | Lượt xem: 7178 | Chuyên mục: Android


1. SQLite database

  1. SQLite là một cơ sở dữ liệu SQL mã nguồn mở, nó lưu trữ dữ liệu vào một tập tin văn bản trên một thiết bị. Nó mặc định đã được tích hợp trên thiết bị Android. Để truy cập dữ liệu này, bạn không cần phải thiết lập bất kỳ loại kết nối nào cho nó như JDBC, ODBC, ... SQLite được Richard Hipp viết dưới dạng thư viện bằng ngôn ngữ lập trình C.
  2. SQLite có các ưu điểm sau:Tin cậy: các hoạt động transaction (chuyển giao) nội trong cơ sở dữ liệu được thực hiện trọn vẹn, không gây lỗi khi xảy ra sự cố phần cứngTuân theo chuẩn SQL92 (chỉ có một vài đặc điểm không hỗ trợ)Không cần cài đặt cấu hìnhKích thước chương trình gọn nhẹ, với cấu hình đầy đủ chỉ không đầy 300 kBThực hiện các thao tác đơn giản nhanh hơn các hệ thống cơ sở dữ liệu khách/chủ khácKhông cần phần mềm phụ trợPhần mềm tự do với mã nguồn mở, được chú thích rõ ràng
  3. Tin cậy: các hoạt động transaction (chuyển giao) nội trong cơ sở dữ liệu được thực hiện trọn vẹn, không gây lỗi khi xảy ra sự cố phần cứng
  4. Tuân theo chuẩn SQL92 (chỉ có một vài đặc điểm không hỗ trợ)
  5. Không cần cài đặt cấu hình
  6. Kích thước chương trình gọn nhẹ, với cấu hình đầy đủ chỉ không đầy 300 kB
  7. Thực hiện các thao tác đơn giản nhanh hơn các hệ thống cơ sở dữ liệu khách/chủ khác
  8. Không cần phần mềm phụ trợ
  9. Phần mềm tự do với mã nguồn mở, được chú thích rõ ràng

2 Cách sử dụng SQLite

Đầu tiên, để thao tác với SQLite, ta phải dùng 2 đối tượng
  1. SQLiteOpenHelper: đối tượng dùng để tạo, nâng cấp, đóng mở kết nối CSDL
  2. SQLiteDatabase: đối tượng dùng để thực thi các câu lệnh SQL trên một CSDL
1. SQLiteOpenHelper
Lớp này có 2 hàm khởi tạo, một hàm 4 tham số, một hàm 5 tham số, tuy nhiên, ta chủ yếu làm việc với hàm 4 tham số
  1. Tham số 1: Context context: Context là một lớp trừu tượng của hệ thống, chứa thông tin môi trường ứng dụng, cung cấp các phương thức để có thể tương tác với hệ điều hành, giúp chúng ta dễ dàng truy cập và tương tác tới các tài nguyên của hệ thống...
  2. Tham số 2: String name: Tên database
  3. Tham số 3: CursorFactory factory: thường để null
  4. Tham số 4: Int version: version của database
Khi khởi tạo một đối tượng của lớp này, ta phải ghi đè 2 phương thức
  1. onCreate(): phương thức này được gọi bởi framework, nếu có yêu cầu truy cập database mà lại chưa khởi tạo database, ở đây ta phải viết code khởi tạo database, cụ thể là khởi tạo bảng (chú ý: khi khởi tạo bảng, ta phải đặt tên khóa chính là _id)
  2. onUpgrade(): phương thức này được dùng khi ứng dụng của bạn có nhiều phiên bản database đc thêm vào. Nó sẽ cập nhật database hiện có hoặc khởi tạo lại thông qua onCreate().
Lớp này có 2 phương thức getReadableDatabase() (chỉ đọc) và getWriteableDatabase() (cho phép ghi đọc). Thông qua 2 phương thức này, ta có thể tạo ra một đối tượng SQLiteDatabase
2. SQLiteDatabase
Lớp này có các phương thức sau để làm việc với SQLite
  1. insert()
  2. update()
  3. delete()
  4. execSQL(): thực thi một câu lệnh SQL trực tiếp
  5. query(): dùng truy vấn
2.1. query()
Các tham số của phương thức này như sau
Ta lấy ví dụ dãy tham số thứ 2 cho tổng quát
  1. tham số 1 là có cho phép distinct hay không
  2. tham số 2 là tên bảng (Chú ý tên bảng và tên database là khác nhau).
  3. tham số 3 là mảng các cột sẽ trả lại, để null nghĩa là trả lại tất cả các cột, để null giống như select *, còn để một mảng giống như select cot1 cot2.
  4. tham số 4 là điều kiện, để null nghĩa là không có đk.
  5. tham số 9 là limit nghĩa là giới hạn số dòng lấy về.
  6. Các tham số còn lại mình không rõ, thường để null, các bạn gg thêm nhé
Câu lệnh truy vấn này trả về một đối tượng Cursor, xem phần riêng về đối tượng Cursor
2.2. insert()
Sử dụng phương thức này để insert một bản ghi vào CSDLVí dụ. ta có một đối tượng database thuộc kiểu SQLiteDatabaseĐể insert, đầu tiên cần tạo một ContentValue (sẽ giải thích ở phần riêng)
ContentValues ct = new ContentValues();
ct.put("full_name", "vncoder.vn");
ct.put("student_id", "2021");
ct.put("gender", 1);
ct.put("year", 21);
Sau đó insert
database.insert(DATABASE_NAME,null,ct);
2.3. update()
Ví dụ, ta có một đối tượng sinh viên được lưu trữ trong CSDL như sau
  1. khóa chính: _id = 2
  2. full_name = “vncoder.vn"
  3. student_id = “20192010”
  4. gender = 1
  5. year = 21
và một đối tượng SQLiteDatabase là sqlDBTa muốn update bản ghi này cho year = 22.Đầu tiên cần lấy ra được bản ghi, sử dụng câu lệnh query()
Cursor cursor = null;
cursor = sqlDB.query(TABLE_NAME, null, "student_id = " + studentID, null, null, null, null);
cursor.moveToFirst();
SinhVien sv = new SinhVien(cursor.getInt(0),cursor.getString(1), cursor.getString(2), cursor.getInt(3), 22);
ở đây, điều quan trọng là ta đã lấy ra được khóa chính _id là cursor.getInt(0), sau đó gán cho thuộc tính id của đối tượng sv. Đây chính là điểm mấu chốt giúp ta có được điều kiện update
Tiếp theo, ta thực hiện update
ContentValues ct = new ContentValues();
ct.put("full_name", sv.fullName);
ct.put("student_id", sv.studentID);
ct.put("gender", sv.gender);
ct.put("year", sv.year);
sqlDB.update(TABLE_NAME, ct, "_id = " + sv.id, null );
3. ContentValues
Các đối tượng ContentValues cho phép xác định khóa / giá trị. Các key đại diện nhận dạng cột bảng và value đại diện cho nội dung cho các bảng ghi trong cột này. ContentValues Có thể được sử dụng để chèn và cập nhật các mục cơ sở dữ liệuVí dụ:
ContentValues ct = new ContentValues();
ct.put("full_name", "vncoder.vn");
ct.put("student_id", "20192010");
ct.put("gender", 1);
ct.put("year", 21);
Full_name, student_id,gender,year là tên các cột, và bên cạnh là giá trị của chúng.
Nếu muốn thêm 2 dòng, ta chỉ cần
ContentValues ct = new ContentValues();
ct.put("full_name", "vncoder.vn");
ct.put("student_id", "20192010");
ct.put("gender", 1);
ct.put("year", 21);
ct.put("full_name", "www vncoder.vn");
ct.put("student_id", "20192010");
ct.put("gender", 0);
ct.put("year", 19);
Chứ không phải tạo ra một đối tượng ContentValue mới, khi đó hàm insert ở trên sẽ trả về số kiểu long là 2
4. Cursor
Đối tượng cursor hiểu đơn giản là một con trỏ, trỏ đến kết quả trả về của câu truy vấn. con trỏ này trỏ đến cái bảng trả về của câu truy vấnVí dụ:
Cursor cursor = database.query(TABLE_NAME, null, null, null, null, null, null);
Phương thức cursor.getCount() trả về số dòng của bảng kết quả
Đầu tiên ta di chuyển con trỏ này lên đầu bảng cursor.moveToFirst();Sau khi đọc xong một dòng chạy lệnh cursor.moveToNext(); để sang dòng tiếp theoKhi cursor ở cuối bảng, không trỏ vào dòng nào, phương thức cursor.isAfterLast()Sẽ trả về giá trị trueĐể lấy ra thông tin, dung phương thức cursor.getString(), cursor.getInt()

3. Demo

Trong ví dụ này chúng ta sẽ cũng nhau làm 1 ứng dụng quản lý thông tin sinh viên có chức năng thêm sửa xóa với giao diện ListView
Bước đầu chúng ta cần một đối tượng Student có các thuộc tính như ID, Name, Address, PhoneNumber, Email, không quên getter setter và constructor.
Student.java
public class Student {
    private int mID;
    private String mName;
    private String mAddress;
    private String mPhoneNumber;
    private String mEmail;

    public Student() {
    }

    public Student(String mName, String mAddress, String mPhoneNumber, String mEmail) {
        this.mName = mName;
        this.mAddress = mAddress;
        this.mPhoneNumber = mPhoneNumber;
        this.mEmail = mEmail;
    }

    public Student(int mID, String mName, String mAddress, String mPhoneNumber, String mEmail) {
        this.mID = mID;
        this.mName = mName;
        this.mAddress = mAddress;
        this.mPhoneNumber = mPhoneNumber;
        this.mEmail = mEmail;
    }

    public int getmID() {
        return mID;
    }

    public void setmID(int mID) {
        this.mID = mID;
    }

    public String getmName() {
        return mName;
    }

    public void setmName(String mName) {
        this.mName = mName;
    }

    public String getmAddress() {
        return mAddress;
    }

    public void setmAddress(String mAddress) {
        this.mAddress = mAddress;
    }

    public String getmPhoneNumber() {
        return mPhoneNumber;
    }

    public void setmPhoneNumber(String mPhoneNumber) {
        this.mPhoneNumber = mPhoneNumber;
    }

    public String getmEmail() {
        return mEmail;
    }

    public void setmEmail(String mEmail) {
        this.mEmail = mEmail;
    }
}
DBManager.java
Các bạn tạo thêm một Java Class mới và đặt tên là DBManager, sau đó các bạn cho nó extends từ SQLiteOpenHelper. Lúc này Class sẽ báo lỗi do thiếu một vài phương thức, các bạn lần lượt tạo một Constructor và 2 phương thức onCreate và onUpgrade cho Class là hết lỗi ngay!!.
Tiếp theo là tạo bảng CREATE TABLE , tên bảng TABLE_NAME và các thuộc tính mà bạn muốn lưu trữ.
public class DBManager extends SQLiteOpenHelper {
    private final String TAG = "DBManager";
    private static final String DATABASE_NAME = "students_manager";
    private static final String TABLE_NAME = "students";
    private static final String ID = "id";
    private static final String NAME = "name";
    private static final String ADDRESS = "address";
    private static final String PHONE_NUMBER = "phone";
    private static final String EMAIL = "email";
    private static int VERSION = 1;

    private Context context;
    private String SQLQuery = "CREATE TABLE " + TABLE_NAME + " (" +
            ID + " integer primary key, " +
            NAME + " TEXT, " +
            EMAIL + " TEXT, " +
            PHONE_NUMBER + " TEXT, " +
            ADDRESS + " TEXT)";


    public DBManager(Context context) {
        super(context, DATABASE_NAME, null, VERSION);
        this.context = context;
        Log.d(TAG, "DBManager: ");
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(SQLQuery);
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        Log.d(TAG, "onUpgrade: ");
    }
Hàm thêm đối tượng Student.
public void addStudent(Student student) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(NAME, student.getmName());
        values.put(ADDRESS, student.getmAddress());
        values.put(PHONE_NUMBER, student.getmPhoneNumber());
        values.put(EMAIL, student.getmEmail());

        db.insert(TABLE_NAME, null, values);
        db.close();
        Log.d(TAG, "addStudent Successfuly");
    }
Hiển thị danh sách ;
public List<Student> getAllStudent() {
        List<Student> listStudent = new ArrayList<>();

        String selectQuery = "SELECT * FROM " + TABLE_NAME;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery,null);
        if (cursor.moveToFirst()) {
            do {
                Student student = new Student();
                student.setmID(cursor.getInt(0));
                student.setmName(cursor.getString(1)+"");
                student.setmEmail(cursor.getString(2));
                student.setmPhoneNumber(cursor.getString(3));
                student.setmAddress(cursor.getString(4));
                listStudent.add(student);

            } while (cursor.moveToNext());
        }
        db.close();
    return listStudent;
    }
Update và xóa đối tượng.
public int updateStudent(Student student){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(NAME,student.getmName());
        contentValues.put(ADDRESS,student.getmAddress());
        contentValues.put(EMAIL,student.getmEmail());
        contentValues.put(PHONE_NUMBER,student.getmPhoneNumber());
        return db.update(TABLE_NAME,contentValues,ID+"=?",new String[]{String.valueOf(student.getmID())});
    }
    public int deleteStudent(int id){
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete(TABLE_NAME,ID+"=?",new String[] {String.valueOf(id)});
    }
Hàm MainActivity.java
import androidx.appcompat.app.AppCompatActivity;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    private EditText edtName;
    private EditText editAddress;
    private EditText edtPhoneNumber;
    private EditText edtEmail;
    private EditText edtId;
    private Button btnSave;
    private Button btnUpdate;
    private ListView lvStudent;
    private DBManager dbManager;
    private CustomAdapter customAdapter;
    private List<Student> studentList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbManager = new DBManager(this);
        initWidget();
        studentList = dbManager.getAllStudent();
        setAdapter();
        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Student student = createStudent();
                if (student != null) {
                    dbManager.addStudent(student);
                }
                updateListStudent();
                setAdapter();
            }
        });
        lvStudent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Student student = studentList.get(position);
                edtId.setText(String.valueOf(student.getmID()));
                edtName.setText(student.getmName());
                editAddress.setText(student.getmAddress());
                edtEmail.setText(student.getmEmail());
                edtPhoneNumber.setText(student.getmPhoneNumber());
                btnSave.setEnabled(false);
                btnUpdate.setEnabled(true);
            }
        });
        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Student student = new Student();
                student.setmID(Integer.parseInt(String.valueOf(edtId.getText())));
                student.setmName(edtName.getText()+"");
                student.setmAddress(editAddress.getText()+"");
                student.setmEmail(edtEmail.getText()+"");
                student.setmPhoneNumber(edtPhoneNumber.getText()+"");
                int result = dbManager.updateStudent(student);
                if(result>0){
                    updateListStudent();
                }
                btnSave.setEnabled(true);
                btnUpdate.setEnabled(false);
            }
        });
        lvStudent.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {
                Student student = studentList.get(position);
                int result = dbManager.deleteStudent(student.getmID());
                if(result>0){
                    Toast.makeText(MainActivity.this, "Delete successfuly", Toast.LENGTH_SHORT).show();
                    updateListStudent();
                }else{
                    Toast.makeText(MainActivity.this, "Delete fail", Toast.LENGTH_SHORT).show();
                }
                return false;
            }
        });
    }

    private Student createStudent() {
        String name = edtName.getText().toString();
        String address = String.valueOf(editAddress.getText());
        String phoneNumber = edtPhoneNumber.getText() + "";
        String email = edtEmail.getText().toString();

        Student student = new Student(name, address, phoneNumber, email);
        return student;
    }

    private void initWidget() {
        edtName = (EditText) findViewById(R.id.edt_name);
        editAddress = (EditText) findViewById(R.id.edt_address);
        edtPhoneNumber = (EditText) findViewById(R.id.edt_number);
        edtEmail = (EditText) findViewById(R.id.edt_email);
        btnSave = (Button) findViewById(R.id.btn_save);
        lvStudent = (ListView) findViewById(R.id.lv_student);
        edtId = (EditText) findViewById(R.id.edt_id);
        btnUpdate = (Button) findViewById(R.id.btn_update);
    }

    private void setAdapter() {
        if (customAdapter == null) {
            customAdapter = new CustomAdapter(this, R.layout.item_list_student, studentList);
            lvStudent.setAdapter(customAdapter);
        }else{
            customAdapter.notifyDataSetChanged();
            lvStudent.setSelection(customAdapter.getCount()-1);
        }
    }
    public void updateListStudent(){
        studentList.clear();
        studentList.addAll(dbManager.getAllStudent());
        if(customAdapter!= null){
            customAdapter.notifyDataSetChanged();
        }
    }

}
Link code cho các bạn tham khảo tại đây
Bài tiếp theo: Android notification >>
vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!