ตัวอย่างการใช้งาน SQLite บน Android ตอนที่ 1


Update! สำหรับคนที่สงสัยเกี่ยวกับการเรียกดูข้อมูลในฐานข้อมูลได้อย่างไร ติดตามอ่านบทความได้ที่นี่ครับ วิธีการเรียกดูข้อมูล SQLite จาก Emulator

วันนี้จะมาพูดถึงเรื่องของ Android SQLite กันนะครับ ตัวแอพพลิเคชันที่ทำเป็น Demo ก็เสร็จนานแล้ว เหลือแต่ช่วงเขียนบทความนี่แหละ ยังหาเวลาเขียนลงตัวไม่ได้ซักที จะว่าไปเรื่องนี้น่าจะเป็นเรื่อง Classic และเป็นเรื่องที่จำเป็นที่นักพัฒนาแอพพลิเคชันแอนดรอยส์ทุกคนจำเป็นต้องรู้ครับ เพราะมันคือการติดต่อฐานข้อมูล เชื่อมต่อฐานข้อมูลกับแอพพลิเคชันของเรา นั่นเอง

SQLite คืออะไร?

SQLite มันก็คือ Library ตัวนึงที่มีขนาดเล็กมาก คอยจัดการ Database ให้กับเรา โดยใช้ Syntax SQL เหมือนกับ MySQL เลย Data Type ที่ SQLite ซับพอร์ตก็คือ TEXT เหมือนกับ String ใน Java, INTEGER เก็บค่าตัวเลขเหมือนกับ long และ REAL เก็บค่าเหมือนกับ double สำหรับใน SQLite ใน Android นั้นมันติดมากับเครื่อง Android ทุกเครื่อง เวลาเขียนแอพเพื่อเชื่อมต่อกับ SQLite ก็ไม่จำเป็นต้องโหลดหรือทำอะไรเพิ่ม เพราะว่าทาง Android นั้นก็ได้เตรียม Class ต่างๆ อำนวยความสะดวกให้เราแล้ว

สำหรับที่อยู่ เวลาเก็บ Database จะถูกเก็บไว้ที่ data/data/PACKAGE_NAME/databases/DB_NAME

Step 1 : Create Project

ไม่พูดมาก เรามาเริ่มสร้างโปรเจ็คกันเลยดีกว่าครับ สำหรับโปรเจ็คนี้เป้าหมายคือ การใช้งาน SQLite และสามารถ CREATE, UPDATE, DELETE ฐานข้อมูลได้ ส่วนตัวแอพพลิเคชันจะประกอบไปด้วย

  • หน้า MainActivity สำหรับแสดง List รายชื่อเพื่อนต่างๆของเรา
  • หน้า AddFriendActivity สำหรับหน้ากรอกข้อมูล เพื่อเพิ่มเพื่อนเข้าสู่ฐานข้อมูล
  • หน้า DetailActivity สำหรับไว้ดูรายละเอียดของเพื่อนคนนั้นๆ

เมื่อวาดออกมาเป็น Diagram ก็จะได้หน้าตาประมาณนี้

SQLite Diagram

ผมไม่พูดถึงวิธีการสร้างโปรเจ็คนะครับ สมมติว่าทุกคนสร้างโปรเจ็คเสร็จแล้ว ต่อมา ดูโครงสร้างของ Database ที่เราจะสร้างกัน เนื่องจากแอพพลิเคชันนี้เป็นแอพสำหรับดูรายละเอียดของเพื่อน ฉะนั้นโครงสร้างของ ฐานข้อมูล ก็จะเป็นลักษณะนี้

SQLite Table

ต่อมาก็สร้างคลาส Model ตั้งชื่อว่า Friend.java ทำการสร้าง Constructor และ Getter, Setter แบบนี้

package com.devahoy.sample.ahoysqlite.model;

public class Friend {

    private int id;
    private String firstName;
    private String lastName;
    private String tel;
    private String email;
    private String description;

    //Default Constructor
    public Friend() {

    }
    //Constructor
    public Friend(int id, String firstName, String lastName, String tel,
                  String email, String description) {

        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.tel = tel;
        this.email = email;
        this.description = description;

    }

    //Getter, Setter

}

Constructor ก็เอาไว้สำหรับ Init ค่า Friend ครับ เวลาสร้างออปเจ็ค Friend ขึ้นมา เช่น id, ชื่อ, นามสกุล, เบอร์โทร, อีเมล์และรายละเอียดต่างๆ

ต่อมา เราก็จะทำการสร้างคลาส เพื่อไว้จัดการ Database ของเรา ผมสร้างคลาสชื่อว่า DBHelper และทำการ extends คลาส SQLiteOpenHelper เจ้าคลาสที่เราทำการ extends นี้มันจะเป็นคลาสที่เอาไว้ช่วยให้เราสร้างฐานข้อมูล , อัพเดทฐานข้อมูลครับ ทำการ implements เมธอด และสร้าง Constructor ดังนี้

package com.devahoy.sample.ahoysqlite.utils;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {

    public DBHelper(Context context) {
        super(context, "devahoy_friends.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

จากด้านบน Constructor จะทำการเรียก super จากนั้นส่ง arguments เป็น Context, ชื่อฐานข้อมูล, CursorFactory, และ เวอร์ชันของ Database ตามลำดับ ส่วนเมธอด onCreate() และ onUpgrade() จะเอาไว้สร้างฐานข้อมูลของเรา และอัพเกรดฐานข้อมูลครับ

@Override
public void onCreate(SQLiteDatabase db) {

    String CREATE_FRIEND_TABLE = "CREATE TABLE friend ( id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "first_name TEXT, last_name TEXT, tel TEXT, email TEXT, description TEXT)";

    db.execSQL(CREATE_FRIEND_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    String DROP_FRIEND_TABLE = "DROP TABLE IF EXISTS friend";

    db.execSQL(DROP_FRIEND_TABLE);

    onCreate(db);
}

เมธอด onCreate() ผมก็ทำการสร้าง SQL Command จากนั้นก็สั่ง db.execSQL(String) เพื่อทำการสร้าง Table จาก String และเมธอด onUpgrade() สำหรับเมื่อมีการเปลี่ยนโครงสร้าง Database หรือมีการเปลี่ยนเวอร์ชัน ก็จะทำการ Drop Table และเรียกเมธอด onCreate(db) เพื่อสร้างใหม่

จะเห็นได้ว่า ที่ onCreate() ผมสั่ง SQL Command เป็น String แบบ hard code เลย ดูแล้วไม่สะดวก หากต้องการแก้ไข หรือเปลี่ยนแปลง Field ต่างๆ ผมก็เลยประกาศเป็นตัวแปรแทน โดยไปเพิ่มตัวแปรที่ model Friend เป็นแบบนี้

public class Friend {
    //Database
    public static final String DATABASE_NAME = "devahoy_friends.db";
    public static final int DATABASE_VERSION = 1;
    public static final String TABLE = "friend";

    public class Column {
        public static final String ID = BaseColumns._ID;
        public static final String FIRST_NAME = "first_name";
        public static final String LAST_NAME = "last_name";
        public static final String TEL = "tel";
        public static final String EMAIL = "email";
        public static final String DESCRIPTION = "description";
    }
    ...
}

เพื่ออะไร? เพื่อสร้างเป็นค่าคงที่สำหรับเก็บชื่อฐานข้อมูล เก็บชื่อ table และก็เก็บค่า column ในฐานข้อมูล กลับมาที่ไฟล์ DBHelper คราวนี้จากใช้ SQL แบบ hard code ก็เปลี่ยนมาใช้ String.format แบบนี้

String CREATE_FRIEND_TABLE = String.format("CREATE TABLE %s " +
        "(%s INTEGER PRIMARY KEY  AUTOINCREMENT, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT)",
        Friend.TABLE,
        Friend.Column.ID,
        Friend.Column.FIRST_NAME,
        Friend.Column.LAST_NAME,
        Friend.Column.TEL,
        Friend.Column.EMAIL,
        Friend.Column.DESCRIPTION);

เครื่องหมาย %s ตัวแรก ก็คือ Friend.TABLE, %s ตัวสองคือ Friend.Column.ID ไล่ไปเรื่อยๆ

สุดท้ายไฟล์ DBHelper ก็จะได้แบบนี้

package com.devahoy.sample.ahoysqlite.utils;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;


public class DBHelper extends SQLiteOpenHelper {

    private final String TAG = getClass().getSimpleName();

    private SQLiteDatabase sqLiteDatabase;

    public DBHelper(Context context) {
        super(context, Friend.DATABASE_NAME, null, Friend.DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        String CREATE_FRIEND_TABLE = String.format("CREATE TABLE %s " +
                "(%s INTEGER PRIMARY KEY  AUTOINCREMENT, %s TEXT, %s TEXT, %s TEXT, %s TEXT, %s TEXT)",
                Friend.TABLE,
                Friend.Column.ID,
                Friend.Column.FIRST_NAME,
                Friend.Column.LAST_NAME,
                Friend.Column.TEL,
                Friend.Column.EMAIL,
                Friend.Column.DESCRIPTION);

        Log.i(TAG, CREATE_FRIEND_TABLE);

        // create friend table
        db.execSQL(CREATE_FRIEND_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        String DROP_FRIEND_TABLE = "DROP TABLE IF EXISTS " + Friend.TABLE;

        db.execSQL(DROP_FRIEND_TABLE);

        Log.i(TAG, "Upgrade Database from " + oldVersion + " to " + newVersion);

        onCreate(db);
    }

ทีนี้เมื่อเราสร้าง DBHelper เสร็จแล้ว ต่อไปเราจะใช้มันยังไง?

Step 2 : สร้าง ListView

ต่อมาก็จะทำการสร้าง Layout สำหรับแสดงรายชื่อเพื่อนนะครับ แต่ว่าผมจะใช้การ extends ListActivity ฉะนั้นก็เลยไม่จำเป็นต้องสร้างไฟล์เลเอาท์ ก็ข้ามไปสร้าง MainActivity.java เลย หรือจะใช้คลาสเดิมก็ได้ ทำการ extends ListActivity ครับ เพื่อจะแสดง ListView เฉยๆ ตัวคลาสจะได้ดังนี้

package com.devahoy.sample.ahoysqlite;

import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.devahoy.sample.ahoysqlite.model.Friend;
import com.devahoy.sample.ahoysqlite.utils.DBHelper;

import java.util.List;


public class MainActivity extends ListActivity {

    DBHelper mHelper;
    List<String> friends;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String[] lists = {""};

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, lists);
        setListAdapter(adapter);
    }
}

จะเห็นได้ว่าโครงสร้างของคลาส ไม่มีอะไรมาก ก็คือจะทำการสร้าง ListView ด้วย ArrayAdapter จากรายชื่อเพื่อนในฐานข้อมูล แต่ว่าตอนนี้ยังไม่ได้ Query อะไร ก็จะใส่เป็น lists แบบไม่มีอะไรไปก่อน android.R.layout.simple_list_item_1 นั้นเป็น Layout ของทาง Android นะครับ

สำหรับใครไม่รู้เรื่อง ListActivity สามารถอ่านเพิ่มได้ที่บทความนี้ครับ การสร้าง ListView แบบง่ายๆ

Step 3: Query SQLite

มาถึงการ Query ฐานข้อมูลกันบ้าง กลับมาที่คลาส DBHelper ต่อครับ ผมจะทำการสร้างเมธอดขึ้นมาใหม่ เพื่อทำการ Query จากนั้นก็จะส่งข้อมูลกลับไปเป็น List<String> เพื่อเอาไปแสดงใน ListView หน้า MainActivity ก็เลยทำการตั้งชื่อเมธอดว่า getFriendList()

public List<String> getFriendList() {
    List<String> friends = new ArrayList<String>();

    sqLiteDatabase = this.getWritableDatabase();

    Cursor cursor = sqLiteDatabase.query
            (Friend.TABLE, null, null, null, null, null, null);

    if (cursor != null) {
        cursor.moveToFirst();
    }

    while(!cursor.isAfterLast()) {

        friends.add(cursor.getLong(0) + " " +
                cursor.getString(1) + " " +
                cursor.getString(2));

        cursor.moveToNext();
    }

    sqLiteDatabase.close();

    return friends;
}

จะเห็นได้ว่า ผมเริ่มทำการสร้าง SQL Statement เพื่อจะ Query จากฐานข้อมูล เริ่มแรกให้ this.getWriteableDatabase() เพื่อให้เข้าถึงการอ่านฐานข้อมูลนั่นเอง จากนั้นก็ทำการ Query ด้วยคำสั่ง query โดยส่งพารามิเตอร์เป็น ชื่อ Table ส่วนอันอื่นเป็น null คือ Query ข้อมูลจาก Table ชื่อ Friend ทั้งหมด มีค่าเท่ากับ SELECT * FROM friend จากนั้นก็วนลูป ส่งค่า List<String> กลับไปนั่นเอง

Note: สำหรับ cursor.getXXXX(int) คือการ get ค่าด้วย Type ที่กำหนด ใน Column ตำแหน่งต่างๆ เช่น cursor.getLong(0) ก็จะทำการ get ค่า id, getString(1) ก็จะทำการ get ค่า firstname ออกมา และ getString(2) ก็จะทำการ get ค่า lastname ออกมาตามลำดับ

เท่านี้ในส่วนของการ Query รายชื่อเพื่อน ก็เรียบร้อย ต่อไปก็กลับไปที่คลาส MainActivity

Step 4: โชว์รายชื่อเพื่อน

เมื่อเราทำการสร้างเมธอดใน DBHelper เสร็จแล้ว ต่อไปเราก็จะเรียกใช้มันที่ MainActivity กันครับ

public class MainActivity extends ListActivity {

    DBHelper mHelper;
    List<String> friends;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mHelper = new DBHelper(this);
        friends = mHelper.getFriendList();

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, friends);

        setListAdapter(adapter);
    }
}

ที่เมธอด onCreate() ทำการสร้าง new instance ของ DBHelper จากนั้นก็เรียกเมธอด getFriendList() เพื่อส่งค่ากลับมาที่ตัวแปร friends

ทดสอบรันโปรแกรมครับ จะเห็นความว่างเปล่า ไม่มีอะไร ฮ่าๆ :D

ตอนนี้เรายังไม่รู้จักวิธีการ INSERT, UPDATE, DELETE ฉะนั้นก็ใช้วิธี เอา db ที่ผมสร้างไว้ devahoy_friends.db เอาไปใช้ก่อน โดยเปิด DDMS จากนั้นเลือกไปที่ data/data/com.devahoy.sample.ahoysqlite/databases แล้วก็กด Push a File into Device นำไฟล์ devahoy_friends.db ไปใส่ จากนั้นทดสอบ รันแอพพลิเคชันครับ จะเห็นรายชื่อเพื่อนขึ้นมาแล้ว

Ahoy List

ส่วนการ INSERT, UPDATE, DELETE ต่อ Part 2 ที่นี่ครับ สำหรับบทความนี้ขอจบเท่านี้ก่อน

Source Code

Chai

Chai Phonbopit : Developer แห่งหนึ่ง • ผู้ชายธรรมดาๆ ที่ชื่นชอบ Node.js, JavaScript และ Open Source มีงานอดิเรกเป็น Acoustic Guitar และ Football

บทความล่าสุด