ایجاد و استفاده از دیتابیس
بسم الله الرحمن الرحیم
ایجاد و استفاده از دیتابیس
فصل ششم-بخش سوم
همان طور که تا حال مشاهده کرده اید تمام تکنو لوژ های موجود یک راه قدیمی برای ذخیره مجموع ای از داده ها دارند. برای ذخیره داده های ارتباطی (Realation Date) استفاده از دیتابیس بسیار کارامد می باشد. به عنوان مثال اگر شما می خواهید نتایج امتحانات دانش آموزان یک مدرسه را ذخیره کنید استفاده از دیتابیس بسیار کارا مد می باشد زیرا شما می توانید query های را برای بازیابی دانش آموزان تعیین کنید علاوه بر این استفاده از دیتابیس شما قادر می سازد تا یکپارچه سازی داده ها را با استفاده از از رابط بین محموعه از داده ها به اجرا در آورید.
اندروید از دیتابیس SQLite استفاده می کند. دیتابیس که شما برای برنامه کاربردی خود ایجاد می کنید فقط از طریق همان برنامه قابل دسترسی و دیگر برنامه به آن دسترسی ندارند.
در این بخش شما یاد می گیرید که چگونه می توان با برنامه نویسی یک دیتابیس SQLiteبرای برنامه کاربردی ایجاد کرد برای اندروید دیتابیسی که شما از طریق برنامه نویسی ایجاد می کنید همیشه در مسیر /data/data/<package_name>/databases ذخیره می شود
ایجاد کلاس کمک کنندDBAdapter
یک تمرین خوب برای کار با دیتابیس ایجاد یک کلاس کمک کننده می باشد که از پیچیدگی های دسترسی به داده های جلوگیری می کند و شما کافی متد های آن را فراخوانی کنید از این رو در این بخش از برنامه شما یک کلاس کمک کننده به نام DBAdapter ایجاد می کنید که این کلاس دیتابیس را ایجاد - باز - بسته و و از دیتابیس Sqlite استفاده می کنید
در این مثال شما دیتابیسی به نامMyDB ایجاد می کنید که دارای جدولی به نام contacts. می باشد و این جدول 3 ستون به نام _id, name, , emailدارد مانند شکل زیر
پروژه جدیدی به نام ایجاد Databases.کنید
کلاس جدیدی به نام DBAdapter ایجاد کنید
در فایل DBAdapter.java دستورات زیر را وارد نمایید.
package com.MehrdadJavididatabases;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
static final String KEY_ROWID = "_id";
static final String KEY_NAME = "name";
static final String KEY_EMAIL = "email";
static final String TAG = "DBAdapter";
static final String DATABASE_NAME = "MyDB";
static final String DATABASE_TABLE = "contacts";
static final int DATABASE_VERSION = 1;
static final String DATABASE_CREATE =
"create table contacts (_id integer primary key autoincrement, "
+ "name text not null, email text not null);";
final Context context;
DatabaseHelper DBHelper;
SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
try {
db.execSQL(DATABASE_CREATE);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS contacts");
onCreate(db);
}
}
//---opens the database---
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
//---insert a contact into the database---
public long insertContact(String name, String email)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_EMAIL, email);
return db.insert(DATABASE_TABLE, null, initialValues);
}
//---deletes a particular contact---
public boolean deleteContact(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
//---retrieves all the contacts---
public Cursor getAllContacts()
{
return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
KEY_EMAIL}, null, null, null, null, null);
}
//---retrieves a particular contact---
public Cursor getContact(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
KEY_NAME, KEY_EMAIL}, KEY_ROWID + "=" + rowId, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
//---updates a contact---
public boolean updateContact(long rowId, String name, String email)
{
ContentValues args = new ContentValues();
args.put(KEY_NAME, name);
args.put(KEY_EMAIL, email);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
}
توضیحات
شما ابتدا ثابت های را برای را که برابر فیلد های جدول در دیتابیسی که می خواهید ایجاد کنید میباشد
static final String KEY_ROWID = "_id";
static final String KEY_NAME = "name";
static final String KEY_EMAIL = "email";
static final String TAG = "DBAdapter";
static final String DATABASE_NAME = "MyDB";
static final String DATABASE_TABLE = "contacts";
static final int DATABASE_VERSION = 1;
static final String DATABASE_CREATE =
"create table contacts (_id integer primary key autoincrement, "
+ "name text not null, email text not null);";
در اینجا ثابت DATABASE_CREATE شامل دستور SQL برای ساخت جدول در دیتابیس MyDBمی می باشد
در کلاس DBAdapter ,شما یک کلاس محلی تعریف کرده اید که از کلاسSQLiteOpenHelper مشتق شده است که این کلاس کمک می کند تا ساخت دیتابیس و نسخه های مختلف دیتابیس را کنترل کنید.
به طور خاص شما متد های onCreate() and onUpgrade را override کردید
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
try {
db.execSQL(DATABASE_CREATE);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS contacts");
onCreate(db);
}
}
متد onCreate() دیتابیس جدیدی را در صورتی که وجود نداشته باشد ایجاد می کند و متد onUpgrade() زمانی فروخوانی می شود که دیتابیس نیازدارد تا به Upgradeشود این کار با چک کردن ثابت DATABASE_VERSION و به کاربردن در متد می شود که شما به سادگی می توانید در متدonUpgrade() به کار ببرید و جدول را حذف و مجدد ایجاد کنید.
شما می توانید متد های دیگر را برای باز کردن و بستن دیتابیس و همجین اضافه کردن ویرایش و باز گرداند مقادیر جدول در د یتابیس تعریف کیند.
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
//---insert a contact into the database---
public long insertContact(String name, String email)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_EMAIL, email);
return db.insert(DATABASE_TABLE, null, initialValues);
}
//---deletes a particular contact---
public boolean deleteContact(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
//---retrieves all the contacts---
public Cursor getAllContacts()
{
return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
KEY_EMAIL}, null, null, null, null, null);
}
//---retrieves a particular contact---
public Cursor getContact(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
KEY_NAME, KEY_EMAIL}, KEY_ROWID + "=" + rowId, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
//---updates a contact---
public boolean updateContact(long rowId, String name, String email)
{
ContentValues args = new ContentValues();
args.put(KEY_NAME, name);
args.put(KEY_EMAIL, email);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
توجه کنید که کلاس مقادیر Cursor را برای query بر می گردداند این طور فکر کنید که کلاس Cursor اشاره به یک محموعه از نتایج query های دیتابیس دارد.
استفاد از کلاس Cursor شما قادر می سازد تا بسیار کار ها بر روی سطر های و ستون ها را مدیریت کنید
شما از کلاس ContentValues برای مقادیر name/value استفاده می کنید متد put() شما را قادر می سازد تا key های با نوع داده های متفاوت اضافه کنید.
برای ساخت دیتابیس برنامه توسط کلاس DBAdapter شما یک نمونه از ایجاد DBAdapter کردید
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
که این سازنده DBAdapter یک نمونه از کلاس DatabaseHelper برای ساخت دیتابیس ایجاد می کند
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}}
استفاده از DataBase
شما DBAdapter کلاس ایجاد کردید حال لازم است که از آن برای دیتابیس استفاده کنید در قسمت زیر شما یاد می گیرید که چکونه CRUD (create, read, update and delete) را انجام دهید عملیات های که با دیتابیس انجام می شود.
اضافه کردن Contacts
در ادامه شرح می دهیم که چگونه یک contact اضافه کنید( عملیات اضافه کردن در دیتابیس)
به پروژه قبل رفته و فایل MainActivity.java به صورت زیر تغیر دهید
package com.MehrdadJavididatabases;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db=new DBAdapter(this);
//---add a contact---
db.open();
long id = db.insertContact("Mehrdad Javidi", "Mehrdad.j16367@Gmail.com");
id = db.insertContact("Ali Javidi", "ali@Example.Com");
db.close();
}
}
توضیحات
در اینجا شما یک نمونه از کلاس DBAdapter ایجاد کردید.
DBAdapter db = new DBAdapter(this);
متد insertContact() در صورت درج سطر جدید یک ID را بر می گرداند در غیر این صورت 1- را بر می گرداند
شما در DDMS, می توانید دیتابیس ایجاد شده را مشاهده کنید
بر گرداندن تمام Contacts (تمام سطر های جدول)
برای بر گردان تمام Contact های جدول از متد getAllContacts() در کلاس DBAdapter استفاده می کنیم
فایل Main/activity.java به صورت زیر تغییر می دهیم
package com.MehrdadJavididatabases;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db=new DBAdapter(this);
//---add a contact---
//db.open();
//long id = db.insertContact("Mehrdad Javidi", "Mehrdad.j16367@Gmail.com");
//id = db.insertContact("Ali Javidi", "ali@Example.Com");
//db.close();
db.open();
Cursor c = db.getAllContacts();
if (c.moveToFirst())
{
do {
DisplayContact(c);
} while (c.moveToNext());
}
db.close();
}
public void DisplayContact(Cursor c)
{
Toast.makeText(this,
"id:" + c.getString(0) +"\n" +
"Name:" + c.getString(1) +"\n" +
"Email:" + c.getString(2),
Toast.LENGTH_LONG).show();
}
}
}
برنامه را با F11 اجرا کنید با استفاده از کلاس Toast اطلاعت تمام Contact ها را نمایش می دهیم
توضیحات
متد getAllContacts() تمام contact های ذخیره شده در دیتابیس را بر می می گرداند نتیجه یک شی Cursor می باشد برای نمایش تمام contact ها شما باید از متد moveToFirst() استفاده کنید اگر موفقیت آمیز بود یعنی این که حداقل یک سطر وجود دارد سپس شما جزئیات آن را با متد DisplayContact() نمایش میدهید
بازگردانی فقط یک contact (یک سطر)
باز گرداند یک contact با استفاده ID, آن .
متد getContact() در کلاس DBAdapter این کار را انجام میدهید
فایل MainActiviy.java به صورت زیر تغییر دهید
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db = new DBAdapter(this);
/*
//---add a contact---
...
//--get all contacts---
...
db.close();
*/
//---get a contact---
db.open();
Cursor c = db.getContact(2);
if (c.moveToFirst())
DisplayContact(c);
else
Toast.makeText(this, “No contact found”, Toast.LENGTH_LONG).show();
db.close();
}
برنامه را اجرا کنید در صورت پیدا شدن آن را نمایش میدهید در غیر این صورت پیغام مناسب نمایش داده می شود.
توضیحات
متد getContact() یک contact را توسط ID بر می گرداند شما ID ان را می دهید. که در اینجا شما 2 را دادید
Cursor c = db.getContact(2);
که در اینجا یک شی Cursor بر می گرداند که توسط متد DisplayContact() جزئیات آن نمایش میدیم.
به روز رسانی Contact
برای بروز رسانی یک contact خاص از متد updateContact() در کلاس DBAdapter استفاده می کنید که Id را دریافت می کند
فایل DatabasesActivity.java به صورت زیر تغیر دهید
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db = new DBAdapter(this);
/*
//---add a contact---
...
//--get all contacts---
...
//---get a contact---
...
db.close();
*/
//---update contact---
db.open();
if (db.updateContact(1, “Wei-Meng Lee”, “weimenglee@gmail.com”))
Toast.makeText(this, “Update successful.”, Toast.LENGTH_LONG).show();
else
Toast.makeText(this, “Update failed.”, Toast.LENGTH_LONG).show();
db.close();
}
برنامه را اجرا کنید در صورت موفقیت آمیز بودن به روز رسانی پیغام مناسبی دریافت می کنید
توضیحات
متد updateContact() در کلاس DBAdapter جزئیات contact را به روز رسانی می کند این متد یک مقدار Boolean را بر می گرداند در صورت با موفقیت بودن True در غیر این صورت False را بر می گرداند
حذف کردن contact
برای حذف کردن contact از متد deleteContact() در کلاس DBAdapter استفاده می کنید
که ID را دریافت می کند
فایل DatabasesActivity.java به صورت زیر تغییر دهید
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db = new DBAdapter(this);
/*
//---add a contact---
...
//--get all contacts---
...
//---get a contact---
...
//---update contact---
...
db.close();
*/
//---delete a contact---
db.open();
if (db.deleteContact(1))
Toast.makeText(this, “Delete successful.”, Toast.LENGTH_LONG).show();
else
Toast.makeText(this, “Delete failed.”, Toast.LENGTH_LONG).show();
db.close();
}
برنامه را اجرا کنید یک پیغام به منزله کوفقیت آمیز بودن حذف نمایش میدهد
توضیحات
متد deleteContact() یک ID را دریافت می کندو بر اساس آن contact را حذف می کند
و یک مقدار Boolean بر می گرداند
Upgrading کردن دیتابیس
بعد از ایجاد و استفاده از دیتابس شما ممکن است جداول اضافه کنید یا ساختار جدول را تغییر دهید یا ستون های را به جدول اضافه کنید
برای این کار شما ثابت DATABASE_VERSION به مقدار بالاتر تغییر دهید به عنوان مثال در اینجا از 1 به 2 تغییر دهید.
public class DBAdapter {
static final String KEY_ROWID = “_id”;
static final String KEY_NAME = “name”;
static final String KEY_EMAIL = “email”;
static final String TAG = “DBAdapter”;
static final String DATABASE_NAME = “MyDB”;
static final String DATABASE_TABLE = “contacts”;
static final int DATABASE_VERSION = 2;
قبل از اجرای دستور Delete بالا را غیر فعال کنید در غیر این صورت حذف جدول با خطا مواجه می شود
وقتی برنامه را اجرا می کنید شما در پنجره LogCat پیغام زیر را مشاهده می کنید
DBAdapter(8705): Upgrading database from version 1 to 2, which
will destroy all old data
در بالا شما به سادگی جدول دیتابیس را حذف کردید و جدول جدیدی در آن اضافه کردید. ولی در واقعیت شما ابتدا یک Backup ایجاد می کنید سپس جدول را حذف می کنید.
ساخت دیتابیس از قبل و بدون نیاز به کد نویسی
در واقعیت شما جدول را قبل از اجرای برنامه و بون نیاز به کد نویسی ایجاد می کنید و این کار بسیار کارامد تر می باشد
برای ساخت دیتابیس SQLite از قبل یک نرم افزار وجود دارد به نام SQLite Database Browser که این کار را انجام میدهد. که شما می توانید آن را از آدرس زیر دانلود کنید
http://sourceforge.net/projects/sqlitebrowser/
زمانی که SQLite Database Browser را نصب کردید شما می توانید به صورت رابط گرافیکی جدول Contact را ایجاد کنید
رکورد های هم می توانید به آن اضافه کنید
قدم بعدی آن است که ان را در برنامه استفاده کنید
به پروژه قبلی بروید و دیتابیسی که ایجاد کردید را در فولدر assets بکشید و رها کنید (Drog and Drop).
توجه کنید نام فایل باید حتما باید با حروف کوچک باشد |
فایل DatabasesActivity.java به صورت زیر تغییر دهید
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;
public class DatabasesActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBAdapter db = new DBAdapter(this);
try {
String destPath = “/data/data/” + getPackageName() +
“/databases”;
File f = new File(destPath);
if (!f.exists()) {
f.mkdirs();
f.createNewFile();
//---copy the db from the assets folder into
// the databases folder---
CopyDB(getBaseContext().getAssets().open(“mydb”),
new FileOutputStream(destPath + “/MyDB”));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//---get all contacts---
db.open();
Cursor c = db.getAllContacts();
if (c.moveToFirst())
{
do {
DisplayContact(c);
} while (c.moveToNext());
}
db.close();
}
public void CopyDB(InputStream inputStream,
OutputStream outputStream) throws IOException {
//---copy 1K bytes at a time---
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
public void DisplayContact(Cursor c)
{
Toast.makeText(this,
“id: “ + c.getString(0) + “\n” +
“Name: “ + c.getString(1) + “\n” +
“Email: “ + c.getString(2),
Toast.LENGTH_LONG).show();
}
}
برنامه را اجرا کنید فایل mydb به مسیر /data/data/com.MehrdadJavididatabases/databases/ کپی می شود
توضیحات
شما یک متد به نام CopyDB() ایجاد کردید که یک دیتابیس را از یک مکان به مکان دیگر کپی می کند.
public void CopyDB(InputStream inputStream,
OutputStream outputStream) throws IOException {
//---copy 1K bytes at a time---
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
نکته این است که شی InputStream فایل مبدا را می خواند. سپس با شی OutputStream در مقصد می نویسید زمانی که برنامه اجرا می شود فایل در فولدر assets به /data/data/com.MehrdadJavididatabases/databases/ کپی می شود
try {
String destPath = “/data/data/” + getPackageName() +
“/databases”;
File f = new File(destPath);
if (!f.exists()) {
f.mkdirs();
f.createNewFile();
//---copy the db from the assets folder into
// the databases folder---
CopyDB(getBaseContext().getAssets().open(“mydb”),
new FileOutputStream(destPath + “/MyDB”));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
هر زمان که شما بر نامه را اجرا می کنید دیتابیس در پوشه به کپی می شود و داده های قبلی حذف می وشد برای جلوگیر ی از ای ن کار دیتابیس را حذف کنید