مشکل بزرگ و نادر در دیتابیس ( هشداری که استاد داده بودند ! )
سلام
یه مشکل خیلی بزرگ برام پیش اومده ، همون مشکلی که استاد در آموزش دیتابیس گفتن که اگر cursor بسته نشه دیگه تحت هیچ شرایط برنامه بالا نمیاد . خب از همون اوائل ( یک سال پیش ) که این آموزش رو دیدم یک عادت خوب که داشتم این بود که بعد از ایجاد cursor تمام عملیات مربوط به اون رو داخل try میذاشتم و در catch میگفتم که cursor.close ، تا در صورت خطا cursor بسته شه . تا الانم مشکلی نداشتم و همیشه دیتابیس رو تغییر میدادم و جایگزین میکردم و تست میکردم .
اما الان فایل دیتابیس رو که میریزم داخل assets ، برنامه که اجرا میشه ، در جنی موشن هم فایلم تولید میشه و در File Explorer نشون میده . همون اول فایل رو میکشم بیرون و با SQLite Manager میبینم درسته ، همون فایل خودمه . بعد کار با نرم افزار رو ادامه میدم تا برسه به جایی که از دیتابیس میخواد استفاده کنه . به محض دسترسی به دیتابیس برنامه خطا میده که فلان table وجود نداره و البته در File Explorer هم فایل دیتابیس حجمش کم میشه ( 0.1 میشه ) و یه فایل database-journal.sqlite در کنارش تولید میشه ( البته این فایل دوم همیشه ایجاد میشد ولی فایل اصلی حجمش کم نمیشد ) . حالا فایل اصلی رو میکشم بیرون میبینم که بله ، table ای که میگه وجود نداره و اصلا هیچکدوم از 10 table وجود نداره . الان 3 ساعته هر کار میکنم و فایل اصلی رو جایگزین میکنم ، فایل خراب میشه و تمام جداول از بین میره .
دیگه واقعا داره اعصابم خورد میشه . باید چیکار کنم ؟ کسی همچین مشکلی نداشته ؟ اگه دقیقا به همون علت باشه که استاد گفتن "دیگه برنامه بالا نمیاد" ( که البته در مورد من برنامه بالا میاد ولی موقع دسترسی به دیتابیس ، فایل خراب میشه ) ، حالا راهش چیه ؟ نصب دوباره جنی موشن مشکل رو حل میکنه ؟ ممنونم .

کارهایی که دیروز انجام دادم و به خطا خوردم :
1 - من همیشه برنامه رو روی جنی موشن تست میکردم و وقتی از صحتش مطمئن میشدم روی گوشی هم تست میکردم تا ظاهرش رو در گوشی هم ببینم . دیروز وقتی برنامه در جنی موشن درست کار کرد گوشی رو وصل کردم و برنامه رو اجرا کردم و دیدم نتایج غیر منتظره میده . دیتابیس موجود در گوشی رو بررسی کردم ، و فهمیدم که چون فایل دیتابیس در گوشی موجود بوده ( در تست های قبلی ) دوباره نساخته و باید اول از رو گوشی پاکش میکردم . البته رکورد جدیدی به دیتابیس اضافه نکرده بودم ، ولی به این دلیل میگم باید دوباره کپی میشد ، چون 2 تا از فیلدها ( ستون ها ) رو در SQLite Manager با هم جابجا کرده بودم ( حالا شاید بگین به چه دردی میخوره جابجا کردن ستون ها - دلیلش اینه که یک آرایه ای در برنامه تولید میشه که ترتیبش عناصرش اگه مثل ترتیب ستون های دیتابیس باشه ، من میتونم با فقط یک حلقه رکوردها رو آپدیت کنم و دیگه نیازی به cursor.getColumnIndex نباشه ) . این فایل دیتابیس جدید رو حواسم بود که در جنی موشن جایگزین کنم ولی وقتی اومدم روی گوشی تست کنم این کار رو نکردم و برنامه با همون دیتابیس قبلی کار کرد ، و بررسی که کردم دیدم نتیجه این شده که در یک ستون از نوع integer یک مقدار double ریخته میشد ، البته این double مقدارش 0 بوده که در ستون integer ریخته میشد .
دیتابیس قدیمی روی گوشی رو کپی کردم توی جنی موشن ، تا ببینم همون نتایج غیر منتظره روی جنی موشن هم نشون میده یا نه ، و دیدم که نتایج اشتباهه . اینجا بود که کاملا مطمئن شدم ایراد از چیه ( پاک نکردن دیتابیس قبلی و جایگزین نکردن دیتابیس جدید )
حالا جالب اینجاست که :
اومدم فایل جدید و سالم رو دوباره در جنی موشن ریختم و برنامه رو تست کردم که همون طور که در پاسخ بالا گفتم ایراد میگرفت جداول موجود نیست . یعنی با یکبار اجرا شدن برنامه با دیتابیس اشتباه ، حالا هر چی فایل سالم رو میریزم دیگه کار نمیکنه و فایل خراب میشه .
2 - دومین تغییری که در ساختار دیتابیس دادم این بود که :
خاصیت Auto Increment مربوط به id رو از روی تمام table ها برداشتم . البته با این ساختار 1 هفته میشه دارم کار میکنم و مشکلی نداشتم و رکوردها رو در برنامه به دفعات حذف و اضافه میکردم . این میتونه دلیل باشه ؟ مثلا رکوردی که قبلا با id = 7 وجود داشته و بعد در برنامه توسط کاربر حذف میشه و کاربر دوباره یک رکورد میسازه ، چون جدول Auto Increment نیست ، این رکورد میتونه دوباره id = 7 بگیره . این میتونه خطایی ایجاد کنه ؟

منم همین مشکل رو داشتم ....دیتا بیس کپی میشد ولی درون دیتا بیس جدولی موجود نبود اشکال کار از اینجا بود که
private void copyDB(InputStream inputStream, OutputStream outputStream)throws IOException{
byte[] buffer = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0){
outputStream.write(buffer,0,length );
inputStream.close();
outputStream.close();
}
}
inputStream.close();
outputStream.close();
ایت دو تا دستور رو می بایست خارح دستور نوشته میشد یعنی
private void copyDB(InputStream inputStream, OutputStream outputStream)throws IOException{
byte[] buffer = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0){
outputStream.write(buffer,0,length );
}
inputStream.close();
outputStream.close();
}
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .
drop table
نزدید ؟ در ضمنcursor.close
رو توی بلاکfinally
بزارید که چه بعد ازtry
چه بعد ازcatch
حتماcursor
بسته بشه. (8 سال پیش)