بانک های اطلاعاتی جز جداناپذیر اغلب برنامه های کاربردی هستند. فرقی نمی کند شما بخواهید یک برنامه todo ساده بنویسید یا برنامه پیشرفته مدیریت مالی، در هر صورت شما نیاز به بانک اطلاعاتی دارید. در اندروید هم به طور ویژه به این موضوع پرداخته شده و به صورت پیش فرض بانک اطلاعاتی SQLite پشتیبانی می شود.
اما از شما چه پنهان، برنامه نویسان گوگل در مقایسه با مایکروسافت بسیار بسیار ضعیف عمل کرده اند. هر قدر مایکروسافت در زمینه ابزارهای توسعه پیشرفته عمل کرده، گوگلی ها ضعیف، گیج و اشتباه عمل کرده اند. حجم کارهایی که باید در سال ۲۰۱۴ برای تولید یک برنامه ساده اندروید انجام بدهید، بسیار بیشتر از کاری است که باید برای تولید برنامه ای پیشرفته تر در سال ۲۰۰۰ با استفاده از ویژوال استودیو انجام بدهید!
خب این همه بدگویی از اندروید در اینجا، به خاطر اینست که فرآیند تولید بانک های اطلاعاتی در اندروید و استفاده از آنها بسیار سخت هست. به صورت استاندارد، شما باید کلاسی بنویسید که کلیه کارهای مربوط به بانک اطلاعاتی شما را انجام دهد. این کلاس باید از کلاس SQLiteDatabaseHelper مشتق شود و دو تابع اساسی را پیاده سازی کند، تابع onCreate و تابع onUpgrade.
تابع onCreate وظیفه تولید جداول بانک اطلاعاتی را دارد، تابع onUpgrade نیز وظیفه به روزرسانی ساختار بانک اطلاعاتی در نسخه های بعدی برنامه را دارد. در اینجا بحث ما فراتر از استفاده از این کلاس و توابع است. ما فرض می کنیم که شما با این فرآیند به طور کامل آشنایی دارید ولی از آن لذت نمی برید 🙂
مشکلات زیادی با استفاده از این روش وجود دارد. چرا که شما باید:
- خودتان جداول را بسازید. بنابراین باید اسم نوع تمام ستونهای مورد نظرتان را بدانید. یک راه رایج استفاده از تعریف ثابت هایی برای جلوگیری از اشتباه می باشد.
- در صورتی که بخواهید سطری در بانک اطلاعاتی ایجاد کنید، باید کوئری INSERT را خودتان بسازید. همانطور که می دانید هک های SQL Injection در این مرحله به وجود می آیند. فارغ از این موضوع، ایجاد کوئری ها و نگهداری آنها در طول زمان بسیار سخت و خطازا هست (فرض کنید اسم یکی از ستونها تغییر کند، یا ستونی حذف شود، در این صورت بایستی کوئری های خطادار را در زمان اجرا کشف کرد) این مشکلات برای دستورات به روزرسانی (UPDATE) و حذف (DELETE) نیز، صادق است.
- جستجو و فیلترینگ یکی از پیچیده ترین کارهاست. اگر حرفه ای باشید قطعا تا به حال ابزارهایی برای تولید استاندارد عبارات شرطی ایجاد کرده اید. به جرات میگویم اگر همچنان دستورات SQL را خودتان تهیه می کنید، برنامه نویس حرفه ای نیستید!
- اگر شما حرفه ای تر باشید، به ازای هر جدول بانک اطلاعاتی، یک کلاس ایجاد می کنید که به ازای هر سطر از جدول، یک شی داشته باشید. کار کردن با اشیا بسیار ساده تر است، شما می توانید همه اطلاعات را در یک شی داشته باشید و هر تغییری که لازم داشته باشید را اعمال کنید.
برای حل همه این مشکلات در زیان های برنامه نویسی پیشرفته ابزارهایی تحت عنوان ORM یا Object Relational Mapping وجود دارد. برای مثال هم اکنون مایکروسافت ابزار Entity Framework را ارائه می کند که به ازای هر کلاس اطلاعاتی، یک جدول و به ازای هر پراپرتی آن یک ستون دارد و بعد از خواندن اطلاعات از بانک اطلاعاتی، نمونه ای از کلاس مورد نظر می ساز و اطلاعات پراپرتی های آن را براساس اطلاعات موجود در بانک اطلاعات تنظیم می کند. بعد از اینکه شما از اطلاعات استفاده کردید و تغییراتی در آن اعمال کردید، برای به روز رسانی بانک اطلاعاتی تنها کافیست، همان شی را به تابع مربوطه بفرستید تا تغییرات آن ثبت گردند.
هم اکنون Hibernate (برای جاوا) و NHibernate (برای .نت) پر کاربردترین و مشهور ترین ORM های جهان هستند و ویژگی های بسیار زیادی را دارند.
اما برروی موبایل و اندروید، ما نمی توانیم از توان ابزارهای قوی ای همچون Hibernate استفاده کنیم. در عوض اما، ابزار بسیار کوچک و ساده ای برای انجام خودکار کارهای بانکی وجود دارد به اسم OrmLite که کارکردن با آن بسیار ساده است.
آشنایی با ORMLite
برای کار با OrmLite کافیست ابتدا فایل jar آن را دانلود کنید و در پوشه libs قرار دهید. (ormlite-core-4.43.jar)
سپس کلاس های Entity را یکی یکی تعریف کنید. مثلا کلاس زیر یک کلاس Entity می باشد (هر پراپرتی آن معادل یک ستون در جدول می باشد)
برای مثال کلاس زیر را ببینید:
public class PersonEntity { public PersonEntity() { } @DatabaseField(generatedId = true) private int Id; @DatabaseField private String Name; @DatabaseField private String NationalID; @DatabaseField private String EconomicID; @DatabaseField private String Phone; @DatabaseField private String Mobile; @DatabaseField private String Address; @DatabaseField private String Comment; @DatabaseField private String Photo; @DatabaseField private PersonTypes Type; @DatabaseField private boolean SyncForced; @DatabaseField private int SyncID; }
همانطور که در کد بالا می بینید، کلاس PersonEntity صرفا برای نگهداری اطلاعات تولید شده و هیچ کاربرد دیگری ندارد.
این کلاس متناظر با جدول personentity در بانک اطلاعاتی است و هر فیلد آن متناظر با یکی از ستونهای جدول فوق است.
برای تعیین یک کلاس به عنوان کلاس متناظر با جدول بانک اطلاعاتی، کافیست برروی ستونهای مورد نظر، صفت (Annotation) ستون جدول بانک اطلاعاتی (DatabaseField) را بنویسید. در حالت کلی سه نوع صفت داریم که در ادامه مقاله هر کدام جداگانه معرفی می شوند
تعریف کلاس بانک اطلاعاتی
همانند روش استاندارد اندروید، در هنگام استفاده از ORMLite نیز باید کلاسی برای ارتباط با بانک اطلاعاتی بنویسید. این کلاس باید از کلاس OrmLiteSqliteOpenHelper مشتق شوند. به عنوان نمونه کلاس زیر را ببینید:
package Farayan.FaraBank.Data; public class Database extends OrmLiteSqliteOpenHelper { public Database(Context context) { super(context, "db", null, 1); } @Override public void onCreate(SQLiteDatabase db, ConnectionSource cs) { try { TableUtils.createTable(cs, PersonEntity.class); } catch (SQLException e) { e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2, int arg3) { } }
همانطور که در بالا می بینید تهیه این کلاس بسیار ساده است و برای تولید جداول کافیست کلاس مورد نظر را به تابع TableUtils.createTable ارسال کنید. بقیه کارها را خود این تابع انجام می دهد!
انواع فیلدها
در حالت کلی سه نوع فیلد داریم، فیلد کلید اصلی، فیلد انواع پایه و فیلد ارجاع به سایر جداول
فیلد کلید اصلی
هر سطر در جدول باید دارای یک شناسه منحصر به فرد باشد. این شناسه به موتور بانک اطلاعاتی کمک می کند هر چه سریعتر سطر مورد نظر را بیابد و برگرداند و …. برای استفاده از ORMlite لازم است کلاس دارای یک فیلد عددی (ترجیحا با نام Id) باشد. این فیلد به صورت خودکار با شناسه سطر بانک اطلاعاتی به روز می شود. برای مشخص کردن پراپرتی ای که شناسه درون آن باید نگهداری شود، لازم است برروی آن صفت DatabaseField را با پارامتر generatedId = true اعمال کنید. البته پارامترهای دیگری هم هستند که در مطالب بعدی معرفی می شوند.
فیلد انواع پایه
فیلدی که نوع آن یکی از انواع پایه جاوا مانند int، long، float باشد، می توانند به صورت مستقیم در جدول ذخیره شوند. برای تعیین این فیلد تنها کافیست صفت DatabaseField را برروی فیلد اعمال کنید
فیلد ارجاع
در صورتی که نوع فیلد کلاس Entity دیگری می باشد، (مثلا شما هم کلاس PersonEntity را تعریف کرده اید و هم کلاس OrganizationEnity و در کلاس PersonEntity پراپرتی Organization را تعریف کرده اید که از نوع OrganizationEntity است). لازم نیست (و نباید) تمام اطلاعات کلاس دوم را در جدول کلاس اول ذخیره کنید. تنها کافیست شناسه سطر کلاس دوم را در جدول اول در ستون مربوطه ثبت کنید. برای این منظور باید به صفت DatabaseField گزینه foreign = true را بفرستید. مثال زیر را ببنید:
@DatabaseField(foreign = true) private OrganizationEntity Organization;
ادامه دارد…
با سلام
اگر امکان داردد مقایسه ای از انواع ORM ها انجام دهید
با تشکر
سلام
امیدوارم به زودی بتونم با مطالب بیشتری رد این باره در خدمتتون باشم.
خیلی عالی بود دستتون درد نکنه من این قسمت رو اصلا نفهمیدم:
“””برای تعیین یک کلاس به عنوان کلاس متناظر با جدول بانک اطلاعاتی، کافیست برروی ستونهای مورد نظر، صفت (Annotation) ستون جدول بانک اطلاعاتی (DatabaseField) را بنویسید. در حالت کلی سه نوع صفت داریم که در ادامه مقاله هر کدام جداگانه معرفی می شوند.”””
میشه واضحتر عملی تر توضیح بدید چیکار باید بکنیم؟
ممنون
فرض کنید در برنامه کلاسی دارید به اسم Book و میخواهید اشیای ساخته شده از آن را در پایگاه داده ذخیره کنید. اگر در پایگاه داده یک جدول داشته باشید به اسم Book که ستونهایی مانند name و author دارد، باید ویژگیهای کلاس را با DatabaseField مشخص کنید:
public class Book {
@DatabaseField
private String name;
@DatabaseField
private String author;
}
اول سلام، بعد هم تشکر.
بخاطر کم بودن منابع مجازی فارسی، خوندن یک مطلب شسته رفته به زبون خودمون حسابی حال آدمو جا میاره.
امیدوارم توفیق ادامه ش رو داشته باشید.
یا علی…
با سلام و تشکر از مطلب عالیتون
میشه بگید چطور میشه از orm در دیتابیس های پیش ساخته استفاده کرد؟
من ی دیتابیس پیش ساخته دارم اما نمیدونم چطور باید از orm برای ارتباط باهاش و انجام دستواراتم استفاده کنم
درود بر شما بسیار عالیست
اگر امکان دارد یه مثال کاملی از بانک و ذخیره و اپدیت و جستجو و حذف و… را در اختیار کاربران قرار دهید.
با سپاس فراوان از شما
سلام استفاده کردم بسیار خوب بود خدا خیرت بده .تشکر