گرفتن backup از دیتابیس sqlite در اندروید
سلام در این سری از اموزش های دیتابیس در اندروید میخواهیم به گرفتن نسخه پشتیبان از دیتابیس بپردازیم.یکی از مهم ترین کارهایی که برای هر دیتابیسی لازم است گرفتن نسخه بکاپ از دیتابیس است که در این اموزش به طور کامل به ان پرداخته خواهد شد.
خب برای اینکار ما سه کار اصلی باید انجام دهیم که شامل export و import و restore است.برای اینکار یک کلاس ایجاد میکنیم که همه این عملیات را انجام دهد.در اینجا نام این کلاس را DbExportImport قرار داده ایم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | public class DbExportImport { public static final String TAG = DbExportImport.class.getName(); /** Directory that files are to be read from and written to **/ protected static final File DATABASE_DIRECTORY = new File(Environment.getExternalStorageDirectory(),"MyDirectory"); /** File path of Db to be imported **/ protected static final File IMPORT_FILE = new File(DATABASE_DIRECTORY,"MyDb.db"); public static final String PACKAGE_NAME = "com.example.app"; public static final String DATABASE_NAME = "example.db"; public static final String DATABASE_TABLE = "entryTable"; /** Contains: /data/data/com.example.app/databases/example.db **/ private static final File DATA_DIRECTORY_DATABASE = new File(Environment.getDataDirectory() + "/data/" + PACKAGE_NAME + "/databases/" + DATABASE_NAME ); /** Saves the application database to the * export directory under MyDb.db **/ protected static boolean exportDb(){ if( ! SdIsPresent() ) return false; File dbFile = DATA_DIRECTORY_DATABASE; String filename = "MyDb.db"; File exportDir = DATABASE_DIRECTORY; File file = new File(exportDir, filename); if (!exportDir.exists()) { exportDir.mkdirs(); } try { file.createNewFile(); copyFile(dbFile, file); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** Replaces current database with the IMPORT_FILE if * import database is valid and of the correct type **/ protected static boolean restoreDb(){ if( ! SdIsPresent() ) return false; File exportFile = DATA_DIRECTORY_DATABASE; File importFile = IMPORT_FILE; if( ! checkDbIsValid(importFile) ) return false; if (!importFile.exists()) { Log.d(TAG, "File does not exist"); return false; } try { exportFile.createNewFile(); copyFile(importFile, exportFile); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** Imports the file at IMPORT_FILE **/ protected static boolean importIntoDb(Context ctx){ if( ! SdIsPresent() ) return false; File importFile = IMPORT_FILE; if( ! checkDbIsValid(importFile) ) return false; try{ SQLiteDatabase sqlDb = SQLiteDatabase.openDatabase (importFile.getPath(), null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = sqlDb.query(true, DATABASE_TABLE, null, null, null, null, null, null, null ); DbAdapter dbAdapter = new DbAdapter(ctx); dbAdapter.open(); final int titleColumn = cursor.getColumnIndexOrThrow("title"); final int timestampColumn = cursor.getColumnIndexOrThrow("timestamp"); // Adds all items in cursor to current database cursor.moveToPosition(-1); while(cursor.moveToNext()){ dbAdapter.createQuote( cursor.getString(titleColumn), cursor.getString(timestampColumn) ); } sqlDb.close(); cursor.close(); dbAdapter.close(); } catch( Exception e ){ e.printStackTrace(); return false; } return true; } /** Given an SQLite database file, this checks if the file * is a valid SQLite database and that it contains all the * columns represented by DbAdapter.ALL_COLUMN_KEYS **/ protected static boolean checkDbIsValid( File db ){ try{ SQLiteDatabase sqlDb = SQLiteDatabase.openDatabase (db.getPath(), null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = sqlDb.query(true, DATABASE_TABLE, null, null, null, null, null, null, null ); // ALL_COLUMN_KEYS should be an array of keys of essential columns. // Throws exception if any column is missing for( String s : DbAdapter.ALL_COLUMN_KEYS ){ cursor.getColumnIndexOrThrow(s); } sqlDb.close(); cursor.close(); } catch( IllegalArgumentException e ) { Log.d(TAG, "Database valid but not the right type"); e.printStackTrace(); return false; } catch( SQLiteException e ) { Log.d(TAG, "Database file is invalid."); e.printStackTrace(); return false; } catch( Exception e){ Log.d(TAG, "checkDbIsValid encountered an exception"); e.printStackTrace(); return false; } return true; } private static void copyFile(File src, File dst) throws IOException { FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dst).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } finally { if (inChannel != null) inChannel.close(); if (outChannel != null) outChannel.close(); } } /** Returns whether an SD card is present and writable **/ public static boolean SdIsPresent() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); } } |
خب ابتدا ما نام و مسیر دیتابیس پشتیبان خود را با در IMPORT_FILE مشخص کردیم.همینطور سه متغییر برای داشتن مسیر دیتابیس اصلی که در DATA_DIRECTORY_DATABASE طریقه استفاده از ان ها را میبینید.حالا به بررسی توابع میپردازیم:
exportDb:یک تابع با این نام ایجاد کردیم که وظیفه ایجاد دیتابیس پشتیبان را دارد و با کمی دقت متوجه عملیات های ان می شوید تنها نکته مهم ان تابع copyFile است که در ان استفاده شده است و وظیفه کپی دیتابیس را دارد در واقع از دیتابیس اصلی یک کپی به عنوان پشتیبان میگیرد.
restoreDb:این تابع وظیفه بازگردانی دیتابیس را از دیتابیس پشتیبان دارد همانطور که میبینید بعد از بررسی وجود فایل و و بررسی وجود نسخه پشتیبان با تابع checkDbIsValid که در اخر به ان می رسیم دیتابیس را با دیتابیس پشتیبان جایگزین میکند با استفاده از copyFile که در تابع قبلی هم برای کپی از ان استفاده کردیم.
importIntoDb:خب این تابع همانطور که از نامش پیداست برای وارد کردن فایل ها از نسخه پشتیبان است که با دستورات ان در مباحث sqlite اشنا شدیم.
checkDbIsValid:این تابع وظیفه بررسی دیتابیس را دارد که ایا دیتابیس معتبر است یا خیر.
copyFile:همانطور که قبل تر از ان استفاده کردیم این تابع عملیات کپی را انجام می دهد که بررسی دقیق ان از حوصله این بخش خارج است.
SdIsPresent:برای بررسی sd card از این تابع استفاده میکنیم.
حال که با بخش های مختلف این کلاس اشنا شدیم میتوانیم به راحتی از ان برای گرفتن بکاپ استفاده کنیم.
به پایان این اموزش رسیدیم امیدوارم مفید بوده باشه
موفق باشید…
تشکر از آموزش خوبتان
خواهش می کنم موفق باشید.
سلام خسته نباشید
چگونه من بک اپ و ریستوری را فراخوانی کنم
سلام. کلاس DbAdapter که توی این کد استفاده شده چی هست؟ باید از جایی بگیرم؟ یا میشه import کرد؟ بنده از OrmLite استفاده میکنم و توی برنامه م همچین کلاسی ندارم. ممنون میشم راهنمایی کنید
DbAdapter همان آداپتور دیتابیس است اگر آموزش های قبلی Sqlite را دنبال می کردید متوجه آن می شدید الان می توانید آن کلاس را همانند زیر ایجاد کنید.
موفق باشید.
SQLiteAssetHelper در اندروید منسوخ شده الان از چی باید استفاده کنیم؟
با وارد کردن کتابخانه مسئله حل شد
حالا گیر داده به سه خط زیر در کلاس DbExportImport:
dbAdapter.open();
dbAdapter.createQuote(
for( String s : DbAdapter.ALL_COLUMN_KEYS ){
که البته درستم میگه چون ان متدها در کلاس DbAdapter نیستش برای حل این مسئله باید چکار کرد؟
بنده هنوز با یان مسِله مشکل دارم میشهیک راهنمایی کنید
سلام
من در مورد آدرس دهی دیتابیس مشکل دارم مثلا این قسمت رو نمی دونم
private static final File DATA_DIRECTORY_DATABASE =
new File(Environment.getDataDirectory() +
“/data/” + PACKAGE_NAME +
“/databases/” + DATABASE_NAME );
این قسمت PACKAGE_NAME رو از کجا باید بیارم ؟
سلام نام پکیجتونه ک جلوش هم برای مثال نوشتیم دیگه..ابتدای اکتیویتون نوشته شده.
سلام ممنون از آموزش های خوبتون
اگه بخواهیم اطلاعات موجود در یک جدول رو کپی کنیم داخل یه جدول دیگه چه باید کرد ؟
تعداد و نام ستون ها در دوتا جدول یکی نیست.
میخام به صورت انتخابی بگم مثلا ستون دوم از جدول مرجع را به ستون اول جدول جدید کپی کنه
و در مواقعی هم لازمه که تو کپی کردن یه شرط هم بررسی بشه
مثلا از جدول مرجع مواردی رو تو جدول جدید بریزه که سن افراد(ستون سوم) بالای 50 باشه
سلام
ابتدا باید از دیتابیس اول خود یک query بگیرید که حاوی تمامی اطلاعات باشد بعد از آن باید مقدار هایی را که در query اول به دست آمده را درون یک متود برای insert یا update دیتابیس جدید هست قرار دهید.
موفق باشید.
با سلام
یه سوال :
تفاوت دوتا تابع restoreDb و importIntoDb در این هست که وقتی restoreDb فراخوانی میشه اطلاعات فعلی دیتابیس از بین میره و فایل پشتیبان توی دیتابیس جایگزین میشه و با اجرای importIntoDb اطلاعات فعلی دیتابیس حفظ میشه و اطلاعات فایل جدید هم به اون اضافه میشه
درسته ؟
سلام کاملا درسته.
سلام . سال نو مبارک
امیدورام امسال سال خوبی رو داشته باشید و ساییتون همچنان مثل قبل فعال باشه و پر قدرت به کارتون ادامه بدید.
یه سوال دیگه از این پست داشتم :
در مورد متد importIntoDb :
cursor.getColumnIndexOrThrow(“title”)
cursor.getColumnIndexOrThrow(“timestamp”)
مقادر فوق را میریزه داخل یه متغیر int. عبارت “title” و “timestamp” چی هست ؟ هر دو مربوط به عنوان ستون های جدول هست ؟
بعد هم این دو مقدار داده شده به متد
dbAdapter.createQuote(
cursor.getString(titleColumn),
cursor.getString(timestampColumn)
)
آرگومان اول نام ستون و آرگومان دوم محتوای ستون هست ؟
اگه کلا یه مقدار در مورد این importIntoDb بیشتر توضیح بدین ممنون میشم
با تشکر
سلام و درود
نام ستون title و timestamp زمان مربوط به کپی هست. زمانی که می جدول می خواهد ساخته شود اگر دقت کنید در متود create دو مقدار ورودی به آن ارسال می شود که یکی از آنها عنوان (title) و دیگری زمان یا timestamp است.
موفق باشید.
سلام وقتتون بخیر
میشه یه اموزش برای بکاپ گیری از Room دیتابیس رو توی سایتتون قرار بدین ؟
اصلا امکانش هست که از روم دیتابیس روی حافظه داخلی گوشی بکاپ گرفته بشه ؟