Tìm hiểu SQLite trong Android

SQLite là cơ sở dữ liệu mã nguồn mở, SQLite hỗ trợ chuẩn quan hệ cơ sở dữ liệu giống như hệ cơ sở

dữ liệu SQL. SQLite yêu cầu giới hạn bộ nhớ trong thời gian thực thi là 250 kb. SQLite hỗ trợ

chuẩn dữ liệu kiểu Text giống như kiểu dữ liệu String trong Java, Integer tương tự kiểu Long

trong Java, và kiểu REAL tương tự kiểu Double trong Java. Tất cả các kiểu dữ liệu khác phải được

chuyển đổi thành các kiểu dữ liệu này trước khi được lưu trong cớ sở dữ liệu SQLite không xác

định các kiểu dữ liệu được ghi vào các cột thực tế của các kiểu được định nghĩa, có thể viết kiểu

Integer trong cột String và ngược lại.

1. SQLite in Android

  • SQLite được nhúng trong các thiết bị Android, sử dụng một cơ sở dữ liệu SQLite trong Android

không yêu cầu thủ tục thiết lập hoặc quản lý cơ sở dữ liệu.

Bạn chỉ phải xác định các câu lệnh SQL để tạo và cập nhật cơ sở dữ liệu. Sau đó các cơ sở dữ liệu

được quản lý tự động cho bạn bởi các nền tảng Android.

Truy cập vào một cơ sở dữ liệu SQLite liên quan đến việc truy cập vào hệ thống tập tin. Điều này

có thể được làm chậm. Vì vậy nó được khuyến khích để thực hiện các hoạt động cơ sở dữ liệu không

đồng bộ. Nếu ứng dụng của bạn tạo ra một cơ sở dữ liệu, cơ sở dữ liệu này là bởi mặc định được

lưu trong thư mục DATA/data/APP_NAME/databases/FILENAME.

  • DATA: Là đường dẫn mà bạn có thể get bởi câu lệnh Environment.getDataDirectory().

  • APP_NAME: Là tên ứng dụng của bạn.

  • FILENAME: Là tên cơ dở dữ liệu mà bạn tạo trong ứng dụng

2. Kiến trúc SQLite

  • Để sử dụng SQLite chúng ta cần import gói android.database trong ứng dụng, gói này chứa tất cả

các phương thức cần thiết để làm việc với cơ sở dữ liệu. Để làm việc cơ sở dự liệu SQLite android

chúng ta sử dụng 2 phương thức chính là SQLiteOpenHelper và SQLiteDatabase.

-SQLiteOpenHelper là lớp cung cấp các phương thức getReadableDatabase() và getWriteableDatabase()

để truy cập đến các đối tượng của lớp SQLiteDatabase để đọc và ghi dữ liệu.

  • SQLiteDatabase là lớp cung cấp các phương thức thao tác với cơ sở dữ liệu.

2.1 Tạo và cập nhật cơ sở dữ liệu với SQLiteOpenHelper

  • Để tạo và nâng cấp cơ sở dữ liệu trong ứng dụng Android của bạn, bạn tạo ra một lớp con của lớp

SQLiteOpenHelper.

Trong hàm khởi tạo của lớp con, bạn gọi super() phương thức của SQLiteOpenHelper, ghi tên cơ sở

dữ liệu và phiên bản cơ sở dữ liệu hiện hành.Trong lớp này chúng ta cần ghi đè phương thức tạo và

cập nhật cơ sở dữ liệu. Chúng ta sẽ có hai phương thức được ghi đè là:

  • onCreate(): Phương thức này được gọi bởi framework, cơ sở dữ liệu đã được truy cập nhưng chưa được tạo.

  • onUpgrade(): Phương thức này cho phép bạn cập nhật phiên bản mới cơ sở dữ liệu của bạn hoặc xóa

cơ sở dữ liệu đã tồn tại và cập nhật cơ sở dữ liệu mới thông qua phương thức onCreate(). Cả hai

phương thức này đều nhận đối tượng SQLiteDatabase làm tham số.

2.2 Thao tác cơ sở dữ liệu với SQLiteDatabase

  • SQLiteDatabase là lớp cơ sở để làm việc với cơ sở dữ liệu SQLite trong Android và nó cung cấp

các phương thức mở, truy vấn, cập nhật và đóng cơ sở dữ liệu, ngoài ra còn cung cấp phương thức

execSQL() để truy vấn trực tiếp đến cơ sở dữ liệu.

  • Sử dụng đối tượng ContentValues để định nghĩa key/values. Key định danh cho cột của bảng và

value là giá trị của bản ghi của cột này. ContentValues sử dụng để insert và cập nhật dữ liệu

trong bản ghi. Ngoài ra để truy vấn cơ sở dữ liệu chúng ta sử dụng phương thức rawQuery() và

query() thông qua lớp SQLiteQueryBuilder.

  • SQLiteQueryBuilder là lớp rất thuận tiện giúp truy vấn cơ sở dữ liệu.

  • rawQuery() chấp nhận một câu lệnh lựa chọn như một đầu vào.

Ví dụ:

  Cursor cursor = getReadableDatabase().
  rawQuery("select * from NHAN_VIEN where _id = ?", new String[] { id });
  • query() cung cấp cấu trúc cho câu lệnh SQL đơn giản.
  return database.query(DATABASE_TABLE,
  new String[] { KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY, KEY_DESCRIPTION },
  null, null, null, null, null);
  • Các tham số của phương thức query()

  • String dbName: tên bảng cơ sở dữ liệu

  • String[] columnNames: Trả về danh sách cột của bảng mà bạn muốn, nếu "null" sẽ trả về tất cả các cột của bảng.

  • String whereClause: Điều kiện chọn dữ liệu trả về, nếu tham số này là "null" thì sẽ trả về tất cả các dữ liệu.

  • String[] selectionArgs: Chọn lọc dữ liệu với điều kiện mảng.

  • String[] groupBy: Sẽ nhóm các dòng được trả về, nếu tham số này là "null" thì các dòng trả về sẽ không được nhóm.

  • String[] having: Lọc cho các nhóm, "null" sẽ không lọc nhóm.

  • String[] orderBy: dữ liệu trả về sẽ được sắp xếp, nếu "null" sẽ không sắp xếp.

3. Cursor

  • Một truy vấn cơ sở dữ liệu SQLite luôn trả về một đối tượng Cursor.

Một Cursor đại diện cho kết quả của một truy vấn, sử dụng Cursor Android có thể đệm kết quả một

cách hiệu quả, mà không cần load tất cả dữ liệu trong bộ nhớ, để lấy số phần tử của kết quả truy

vấn sử dụng phương thức getCount(). Để di chuyển dữ liệu giữa các dòng riêng biệt bạn có thể sử

dụng phương thức moveToFirst() và moveToNext(), isAfterLast() là phương thức dùng để kiểm tra xem

đã kết thúc câu lệnh truy vấn đã đạt được. Cursor cung cấp phương thức get() kiểu dữ liệu như :

getLong(columnIndex), getString(columnIndex) để truy cập dữ liệu trong cột tại vị trí hiện tại,

trong đó columnIndex là số cột bạn truy cập. Cursor cũng cung cấp các phương thức

getColumnIndexOrThrow (String) để lấy chỉ số cột cho một tên cột của bảng, sau khi sử dụng Cursor

phải đóng với phương thức close().

- Ví dụ:

- Tạo lớp MainActivity.java
public class MainActivity extends ActionBarActivity {
    private ListView obj;
    DBHelper mydb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mydb = new DBHelper(this);
        ArrayList array_list = mydb.getAllCotacts();
        ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, array_list);

        obj = (ListView) findViewById(R.id.listView1);
        obj.setAdapter(arrayAdapter);
        obj.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                int id_To_Search = arg2 + 1;

                Bundle dataBundle = new Bundle();
                dataBundle.putInt("id", id_To_Search);

                Intent intent = new Intent(getApplicationContext(), DisplayContact.class);

                intent.putExtras(dataBundle);
                startActivity(intent);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);

        switch (item.getItemId()) {
            case R.id.item1:
                Bundle dataBundle = new Bundle();
                dataBundle.putInt("id", 0);

                Intent intent = new Intent(getApplicationContext(), DisplayContact.class);
                intent.putExtras(dataBundle);

                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public boolean onKeyDown(int keycode, KeyEvent event) {
        if (keycode == KeyEvent.KEYCODE_BACK) {
            moveTaskToBack(true);
        }
        return super.onKeyDown(keycode, event);
    }
}
  • Tạo lớp DisplayContact.java
public class DisplayContact extends Activity {
    private DBHelper mydb;

    TextView name;
    TextView phone;
    TextView email;
    TextView street;
    int id_To_Update = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_contact);
        name = (TextView) findViewById(R.id.editTextName);
        phone = (TextView) findViewById(R.id.editTextPhone);
        email = (TextView) findViewById(R.id.editTextStreet);
        street = (TextView) findViewById(R.id.editTextEmail);

        mydb = new DBHelper(this);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            int Value = extras.getInt("id");

            if (Value > 0) {
                Cursor rs = mydb.getData(Value);
                id_To_Update = Value;
                rs.moveToFirst();

                String nam = rs.getString(rs.getColumnIndex(DBHelper.CONTACTS_COLUMN_NAME));
                String phon = rs.getString(rs.getColumnIndex(DBHelper.CONTACTS_COLUMN_PHONE));
                String emai = rs.getString(rs.getColumnIndex(DBHelper.CONTACTS_COLUMN_EMAIL));
                String stree = rs.getString(rs.getColumnIndex(DBHelper.CONTACTS_COLUMN_STREET));

                if (!rs.isClosed()) {
                    rs.close();
                }
                Button b = (Button) findViewById(R.id.button1);
                b.setVisibility(View.INVISIBLE);

                name.setText((CharSequence) nam);
                name.setFocusable(false);
                name.setClickable(false);

                phone.setText((CharSequence) phon);
                phone.setFocusable(false);
                phone.setClickable(false);

                email.setText((CharSequence) emai);
                email.setFocusable(false);
                email.setClickable(false);

                street.setText((CharSequence) stree);
                street.setFocusable(false);
                street.setClickable(false);
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Bundle extras = getIntent().getExtras();

        if (extras != null) {
            int Value = extras.getInt("id");
            if (Value > 0) {
                getMenuInflater().inflate(R.menu.display_contact, menu);
            } else {
                getMenuInflater().inflate(R.menu.menu_main, menu);
            }
        }
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        switch (item.getItemId()) {
            case R.id.Edit_Contact:
                Button b = (Button) findViewById(R.id.button1);
                b.setVisibility(View.VISIBLE);
                name.setEnabled(true);
                name.setFocusableInTouchMode(true);
                name.setClickable(true);

                phone.setEnabled(true);
                phone.setFocusableInTouchMode(true);
                phone.setClickable(true);

                email.setEnabled(true);
                email.setFocusableInTouchMode(true);
                email.setClickable(true);

                street.setEnabled(true);
                street.setFocusableInTouchMode(true);
                street.setClickable(true);

                return true;
            case R.id.Delete_Contact:

                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.deleteContact)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            mydb.deleteContact(id_To_Update);
                            Toast.makeText(getApplicationContext(), "Deleted Successfully", Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                            startActivity(intent);
                        }
                    })
                    .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // User cancelled the dialog
                        }
                    });
                AlertDialog d = builder.create();
                d.setTitle("Are you sure");
                d.show();

                return true;
            default:
                return super.onOptionsItemSelected(item);

        }
    }

    public void run(View view) {
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            int Value = extras.getInt("id");
            if (Value > 0) {
                if (mydb.updateContact(id_To_Update, name.getText().toString(), phone.getText().toString(), email.getText().toString(), street.getText().toString())) {
                    Toast.makeText(getApplicationContext(), "Updated", Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                } else {
                    Toast.makeText(getApplicationContext(), "not Updated", Toast.LENGTH_SHORT).show();
                }
            } else {
                if (mydb.insertContact(name.getText().toString(), phone.getText().toString(), email.getText().toString(), street.getText().toString())) {
                    Toast.makeText(getApplicationContext(), "done", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplicationContext(), "not done", Toast.LENGTH_SHORT).show();
                }
                Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                startActivity(intent);
            }
        }
    }
}
  • DBHelper.java
public class DBHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "framgia.db";
    public static final String CONTACTS_COLUMN_NAME = "name";
    public static final String CONTACTS_COLUMN_EMAIL = "email";
    public static final String CONTACTS_COLUMN_STREET = "street";
    public static final String CONTACTS_COLUMN_CITY = "place";
    public static final String CONTACTS_COLUMN_PHONE = "phone";
    private HashMap hp;

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table contacts " + "(id integer primary key, name text,phone text,email text, street text)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS contacts");
        onCreate(db);
    }

    public boolean insertContact  (String name, String phone, String email, String street)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", name);
        contentValues.put("phone", phone);
        contentValues.put("email", email);
        contentValues.put("street", street);
        db.insert("contacts", null, contentValues);
        return true;
    }

    public Cursor getData(int id){
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor res =  db.rawQuery( "select * from contacts where id="+id+"", null );
        return res;
    }

    public boolean updateContact (Integer id, String name, String phone, String email, String street)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", name);
        contentValues.put("phone", phone);
        contentValues.put("email", email);
        contentValues.put("street", street);
        db.update("contacts", contentValues, "id = ? ", new String[] { Integer.toString(id) } );
        return true;
    }

    public Integer deleteContact (Integer id)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete("contacts",
            "id = ? ",
            new String[] { Integer.toString(id) });
    }

    public ArrayList<String> getAllCotacts()
    {
        ArrayList<String> array_list = new ArrayList<String>();

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor res =  db.rawQuery( "select * from contacts", null );
        res.moveToFirst();

        while(res.isAfterLast() == false){
            array_list.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME)));
            res.moveToNext();
        }
        return array_list;
    }
}
  • activity_display_contact.xml
<ScrollView
    android:id="@+id/scrollView1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".DisplayContact">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="370dp"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">

        <EditText
            android:id="@+id/editTextName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="82dp"
            android:layout_marginTop="5dp"
            android:ems="10"
            android:inputType="text">
        </EditText>

        <EditText
            android:id="@+id/editTextEmail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/editTextStreet"
            android:layout_below="@+id/editTextStreet"
            android:layout_marginTop="22dp"
            android:ems="10"
            android:inputType="textEmailAddress"/>

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/editTextName"
            android:layout_alignParentLeft="true"
            android:text="@string/name"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="28dp"
            android:onClick="run"
            android:text="@string/save"/>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/editTextEmail"
            android:layout_alignLeft="@+id/textView1"
            android:text="@string/email"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/editTextPhone"
            android:layout_alignLeft="@+id/textView1"
            android:text="@string/phone"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@+id/editTextEmail"
            android:layout_alignLeft="@+id/textView5"
            android:text="@string/street"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <EditText
            android:id="@+id/editTextStreet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/editTextName"
            android:layout_below="@+id/editTextPhone"
            android:ems="10"
            android:inputType="text">
            <requestFocus/>
        </EditText>

        <EditText
            android:id="@+id/editTextPhone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/editTextStreet"
            android:layout_below="@+id/editTextName"
            android:ems="10"
            android:inputType="phone|text"/>

    </RelativeLayout>
</ScrollView>
  • AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="activity.geeeksplay.asia.sqliteandroid" >
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".DisplayContact"
                  android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
    </application>
</manifest>
  • Sau khi chạy ứng dụng chúng ta được kết quả như sau:

a1.png

  • Sau khi click vào item sẽ xuất hiện màn hình như sau:

b1.png

  • Click vào Menu chúng ta được màn hình như sau:

c1.png