آموزش دیتابیس اندروید

آموزش دیتابیس اندروید از مبتدی تا پیشرفته – بخش ۴

توی بخش‌های قبل بعد از آشنا شدن با مفهوم دیتابیس، به ساده‌ترین شکل ممکن یک دیتابیس ساختیم.

وارد کردن، خواندن، آپدیت کردن و حذف اطلاعات رو یاد گرفتیم. حالا قصد داریم کم‌کم بریم سمت مباحث پیشرفته‌تر.

در این بخش استفاده اصولی و ساختار یافته دیتابیس پیشرفته اندروید رو یاد میگیریم.

اگر با دیتابیس و مباحث اولیه آشنایی ندارید لازمه ابتدا بخش اول رو از ایـنــجــــا مطالعه کنید.

همچنین آموزش خوندن اطلاعات از دیتابیس رو میتونید توی این مطلب ببینید.

 

شروع کار دیتابیس پیشرفته اندروید

توی بخش های قبلی به این شکل یاد گرفتیم که هرجای برنامه که لازم بود کدهای مربوط به دیتابیس رو بنویسیم. این کار برای پروژه های کوچیک شاید مناسب باشه اما به هیچ عنوان برای پروژه های بزرگ توصیه نمیشه. چرا؟ چون توی پروژه های بزرگ که کار شما با دیتابیس زیاد هست، این روش باعث چند باره نوشتن کدهای تکراری میشه. همچنین این روش به شدت نظم برنامه شما رو به هم میریزه و باعث میشه کدهای بسیار طولانی داشته باشید. حتما توی پروژه های بزرگ پیش میاد که بخواین توی ساختار جدول و دیتابیس تغییری ایجاد کنید و این کار توی حالت قبلی یک دردسر بزرگ و زمان بر هست. مورد مهمتر اینکه توی پروژه‌های بزرگ شما نیاز پیدا میکنید که در ورژن‌های بعدی برنامه با حفظ اطلاعات قبلی کاربر، توی دیتابیس تغییری بدید.

در این بخش میخوایم این مشکل رو حل کنیم. به این شکل که کدهای دیتابیس رو توی کلاس‌های مجزا به صورت توابع مینویسیم و بعد در جای مورد نیاز استفاده میکنیم. این کار باعث میشه کدهای دیتابیس شما یک بار نوشته بشه، جاشون مشخص باشه و تغییر توی اونها سریع انجام بگیره. دیگه لازم نیست برای اضافه کردن یک ستون به جدولتون، ۱۰ جای پروژه رو بگردید و تغییر بدید. (اون هم بعد از صرف وقت زیاد و به خطا خوردن)

 

مرحله اول

توی مرحله اول یک کلاس میسازیم که وظیفه ساختن، باز کردن و آپگرید کردن ساختار دیتابیس رو بر عهده داره. توی این کلاس اطلاعات دیتابیس (نام و شماره ورژن) و ساختار جدول ها مشخص میشه. اسم این کلاس رو به عنوان مثال میذاریم MyDatabase. این کلاس از SQLiteOpenHelper ارث بری میکنه که با نوشتن extends SQLiteOpenHelper جلوی اسمش اینو مشخص میکنیم. و دارای سه تا تابع اصلی هست. شکل کلی کلاس به صورت زیر هست:

package your.package.name;

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

public class MyDatabase extends SQLiteOpenHelper {

    private final static String DB_NAME = "database name";
    private final static int DB_VERSION = 1;

    public static final String tableStudents = "students";
    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String MARK = "mark";

    public MyDatabase(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase mydb) {
        mydb.execSQL("CREATE TABLE IF NOT EXISTS "+ tableStudents + " (" +
                ID + " INTEGER PRIMARY KEY, " +
                NAME + " TEXT, " +
                MARK + " numeric);");
    }

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

    }
}

توضیح

خب حالا این سه تابع اصلی رو توضیح میدیم که چه وظیفه ای دارن. تابع اول که هم اسم خود کلاسمون هست، وظیفه باز کردن یا ساختن دیتابیس رو برعهده داره. این تابع اسم و ورژن دیتابیس رو دریافت میکنه. در صورتی که هنوز دیتابیسی با این اسم ساخته نشده باشه تابع onCreate اجرا میشه.

توی تابع onCreate ما باید ساختار جدول هامون رو مشخص کنیم و بسازیم. کاملا مشابه دستوری که توی بخش اول برای ساخت جدول نوشتیم.

اگر دیتابیس از قبل وجود داشته باشه ولی ورژنی که توی کلاس MyDatabase نوشتیم بزرگتر از ورژن فعلی دیتابیس باشه، تابع onUpgrade اجرا میشه. این تابع همونطور که از اسمش مشخصه عملیات مربوط به آپگرید کردن و تغییر دادن توی ساختار دیتابیس رو انجام میده. مثلا توی ورژن جدید برنامه تصمیم گرفتیم که یک ستون به جدول دانشجوها اضافه کنیم که ایمیل هر دانشجو رو ذخیره کنه. این تغییرات رو توی این تابع باید انجام بدید و باید حواستون باشه که اطلاعات قبلی کاربر در صورتی که اهمیت دارن از بین نره. (در آینده راجع به آپگرید دیتابیس با مثال بیشتر یاد میگیریم)

خب این کلاس رو متوجه شدیم که وظیفش چیه و چکار میکنه و چقدر اهمیت زیادی داره.

 

مرحله دوم

حالا یک کلاس دیگه نیاز داریم تا تمام عملیات مربوط به دیتابیس رو توی اون بنویسیم و سایر جاهای برنامه فقط ازش استفاده کنیم. این کلاس میتونه عملیات وارد کردن، خواندن، آپدیت، حذف و هر کار دیگه مربوط به دیتابیس رو انجام بده. همه چیز مثل قبله فقط با این تفاوت که شما به صورت تابع مینویسید و بعد جاهای دیگه صدا میزنیدش.

اسم این کلاس رو مثلا میتونیم بذاریم DatabaseHelper چون قراره به ما توی دیتابیس کمک کنه. یک نمونه کلی این کلاس میتونه به شکل زیر باشه.

package your.package.name;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DatabaseHelper {

    private SQLiteDatabase mydb;

    public DatabaseHelper(Context context){
        mydb = new MyDatabase(context).getWritableDatabase();
    }

    public void insertToStudents(int id, String name, int age){
        ContentValues values = new ContentValues();
        values.put(MyDatabase.ID, id);
        values.put(MyDatabase.NAME, name);
        values.put(MyDatabase.MARK, age);

        mydb.insert(MyDatabase.tableStudents, null, values);
        mydb.close();
    }

    public void updateMark(int id, int newMark){
        ContentValues values = new ContentValues();
        values.put(MyDatabase.MARK, newMark);

        mydb.update(MyDatabase.tableStudents, values,
                MyDatabase.ID + " = ?",
                new String[] { String.valueOf(id) });
        mydb.close();
    }

    public StudentData[] getAllStudents(){
        Cursor allrows = mydb.rawQuery("select * from " + MyDatabase.tableStudents, null);

        StudentData[] data = new StudentData[allrows.getCount()];
        int i = 0;
        while (allrows.moveToNext()){
            data[i] = new StudentData();
            data[i].id = allrows.getInt(allrows.getColumnIndex(MyDatabase.ID));
            data[i].name = allrows.getString(allrows.getColumnIndex(MyDatabase.NAME));
            data[i].mark = allrows.getInt(allrows.getColumnIndex(MyDatabase.MARK));
        }

        allrows.close();
        mydb.close();
        return data;
    }

    public class StudentData{
        public int id;
        public String name;
        public int mark;
    }
}

توضیح

توی این کلاس همونطور که میبینید ابتدا یک تابع اصلی به اسم DatabaseHelper وجود داره. توی این تابع دیتابیس خودمون رو با استفاده از کلاس MyDatabase که قبلا ساختیم باز میکنیم تا بتونیم توی سایر توابع از دیتابیس استفاده کنیم.

سه تا تابع دلخواه رو به طور نمونه اینجا نوشتیم که به ترتیب عملیات وارد کردن اطلاعات دانشجو (insertToStudents)، آپدیت نمره دانشجو (updateMark) و خواندن اطلاعات تمام دانشجویان (getAllStudents) رو انجام خواهند داد. کاری که این توابع انجام میدن رو قبلا گفتیم و چیز جدیدی نیست.

تنها نکته تابع خواندن اطلاعات هست که بعد از خوندن اطلاعات دانشجوها، نتایج رو به صورت یک آرایه از جنس StudentData برمیگردونه. اطلاعاتی که از جدول میخونیم زیاده و نمیتونیم از یک تابع مثلا سه تا آرایه برای آیدی‌ها، اسم‌ها و نمره‌ها برگردونیم. به همین دلیل مجبوریم که همه رو توی یک آرایه قرار بدیم. و برای اینکه توی یک آرایه بتونیم قرار بدیم باید یک شیء یا کلاس دانشجو بسازیم. این کلاس زیر تابع خوندن تعریف شده و میتونید نحوه استفاده از اون رو ببینید.

 

نحوه استفاده

خب حالا برای استفاده از ساختار جدیدمون کار خیلی راحت و ساده ست. هر جای پروژه که خواستید (مثلا توی MainActivity) به شکل زیر عملیات مختلف رو انجام بدید.

برای وارد کردن اطلاعات یک دانشجو:

new DatabaseHelper(MainActivity.this).insertToStudents(1086, "ali", 18);

آپدیت نمره یک دانشجو با آیدی ۱۰۸۶:

new DatabaseHelper(MainActivity.this).updateMark(1086, 19);

گرفتن اطلاعات تمام دانشجوها و نمایش اونها در یک تکست ویو:

DatabaseHelper.StudentData[] data = new DatabaseHelper(this).getAllStudents();

for(int i = 0; i < data.length; i++){
    myTextView.append("name: " + data[i].name + ", mark: " + data[i].mark + "\n");
}

زیاد سخت نبود، نه؟ توی حجم کم شاید این کارا بیهوده به نظر برسه اما مطمئن باشید اینطور نیست. وقتی حداقل ۵ یا ۶ جدول داشتید و مثلا توی برنامه در ۶۰ جای مختلف نیاز به برقراری ارتباط با دیتابیس بود، فایده این ساختار رو متوجه میشید.

 

در ادامه …

در بخش‌های بعدی سعی میکنم یک پروژه رو به صورت گام به گام توضیح بدم تا اگر اشکالی در عمل و انجام این آموزش داشتید رفع بشه و بتونید پروژه رو پیاده سازی کنید.

لطفا بازخوردهای خودتون رو توی کامنت بنویسید و اگر سوالی داشتید بپرسید.

بخش پنجم: پیاده سازی نمونه پروژه دیتابیس اندروید

آموزش استفاده از دیتابیس آماده

من عاشق برنامه‌نویسی، یاد گرفتن و آموزش دادن هستم. انجام کارای جدید توی برنامه‌نویسی رو بیشتر به چشم سرگرمی میبینم تا کار.

حجت ریحانه

من عاشق برنامه‌نویسی، یاد گرفتن و آموزش دادن هستم. انجام کارای جدید توی برنامه‌نویسی رو بیشتر به چشم سرگرمی میبینم تا کار.

10 ديدگاه بر “آموزش دیتابیس اندروید از مبتدی تا پیشرفته – بخش ۴

  1. سلام خسته نباشید من به تازگی پکیج ساخت کتاب نیک اندروید رو گرفتم و باهاش یه اپ درست کردم که حجمش زیاده و هنگ میکنه و با کویری ها و روش های این آموزش جوابگو نیست شما میتونید کمکم کنید باگ برنامه برطرف بشه؟؟دیتابیس خارجیه ولی روش برای استفاده از دیتای حجیم کاربرد نداره ممنون

    1. سلام
      از اونجایی که پروژه شما ساختارش مشخص نیست, من به صورت کلی نمیتونم کمکتون کنم. مگر اینکه شما تشخیص بدین خطا از کدوم قسمته و اینکه لاگ خطا رو بفرستین.
      دیتابیس آماده رو توی بخش های بعدی حتما آموزش میدیم کامل.

  2. سلام. ممنون از آموزش های خوبتون. خیلی روان، واضح و با مثال های مرتبط بیان شدند. سپاس از وقتی که برای این آموزش رایگان گذاشتید. براتون آرزوی موفقیت دارم.
    میخواستم خواهش کنم آموزش اتصال لیست ویو به یک دیتابیس آماده sqlite رو هم در آموزشهاتون قرار بدید. خیلی از منابع آموزش ایجاد دیتابیس و جداول اون رو داخل خود کد گذاشتن، ولی استفاده از یک دیتابیس آماده اون هم خوندن از دیتابیس برای لیست ویو، خیلی کم آموزش داده شده، مخصوصا در منابع فارسی. باز هم تشکر.

    1. سلام
      ممنون از لطفتون
      آموزش دیتابیس آماده توی برنامه هست و به زودی رو سایت قرار داده میشه.
      موفق باشید

  3. سلام ، سال نو مبارک.
    پس آموزش استفاده از دیتابیس آماده توی برنامه چی شد؟؟ 🙁
    خواهش میکنم آموزش های خوبتون رو ادامه بدین. ممنون.

  4. سلام مجدد…ممنون. مشتاقانه منتظرم.
    یه سوال هم از خدمتتون داشتم. تو داکیومنتای developer.google نوشته مقدار null برای پارامتر دوم متد سازنده کلاس helperمون ، یعنی پارامتر DB_NAME در متد زیر طبق مثال شما:
    public MyDatabase(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
    }
    برای in-memory database هست. منظور از in-memory database چیه و چه موقعی کاربرد داره؟
    ممنون.

    1. سلام مجدد
      منم مشتاقانه منتظرم که در فرصت مناسب آموزش دیتابیس آماده رو بذارم. متاسفانه یکم برنامه‌های کاری به هم ریخت و باعث شد تاخیر بیافته.
      در مورد سوالتون باید بگم که این نوع دیتابیس، به صورت موقت در حافظه رم ایجاد میشه. یعنی به عنوان یک فایل در حافظه گوشی ذخیره نمیشه. و با close کردن دیتابیس یا از بین رفتن برنامه، دیتابیس هم از بین میره.

  5. سلام
    من یه کتاب نوشتم که دیتابیس اماده داره و قراره تو ورژن های بعدی دیتابیس اطلاعاتش اضافه بشه حالا این ورژن دیتابیس اگه تو نسخه های بعدی بیشتر بشه دیتابیس جدید خودکار جایگذین اون قبلی میشه یا باید با کدنویسی اینکارو کنم چون شرط گذاشتم که اگه دیتابیس توحافضه بود دیگه کپی نشه

    1. سلام
      در این مطلبی که شما نظر گذاشتید، باید برای این کار توی تابع onUpgrade کد بنویسید تا مطالب قبلی پاک بشه و مطالب جدید جایگزین بشن.
      اما اگر آموزش دیتابیس آماده رو مطالعه کنید، توی اون آموزش با بالا بردن ورژن، دیتابیس آماده جدید، کاملا جایگزین قبلی میشه.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *