הגירת סכמת מסד נתונים של Room באנדרואיד

עדכוני אפליקציה לא צריכים לגרום לאובדן נתוני משתמשים. אנחנו בונים הגירות סכימת Room נכונות שמבטיחות מעבר חלק בין גרסאות מסד הנתונים. הצוות שלנו מספק את הפרויקט במפתח מלא—מביקורת שינויים ועד בדיקות ותמיכה מתמשכת.

פיתוח ותמיכה בכל סוגי היישומים הניידים:

יישומים ניידים למידע ובידור
אפליקציות חדשות, משחקים, מדריכים, קטלוגים מקוונים, אפליקציות מזג אוויר, אפליקציות כושר ובריאות, אפליקציות נסיעות, אפליקציות חינוכיות, רשתות חברתיות ומסנג'רים, חידונים, בלוגים ופודקאסטים, פורומים, אגרגטורים
יישומים ניידים למסחר אלקטרוני
חנויות מקוונות, אפליקציות B2B, מרקטפלייסים, בורסות מקוונות, שירותי קאשבק, בורסות, פלטפורמות דרופשיפינג, תוכניות נאמנות, משלוחי מזון ומוצרים, מערכות תשלום.
יישומים ניידים לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, ניהול פרויקטים, כלים לצוותי מכירות, ניהול פיננסי, ניהול ייצור, ניהול לוגיסטיקה ומשלוחים, ניהול משאבי אנוש, מערכות ניטור נתונים
יישומים ניידים לשירותים אלקטרוניים
פלטפורמות מודעות מסווגות, בתי ספר מקוונים, בתי קולנוע מקוונים, פלטפורמות שירות אלקטרוניות, פלטפורמות קאשבק, אירוח וידאו, פורטלים נושאיים, פלטפורמות הזמנות ותזמון מקוונות, פלטפורמות מסחר מקוונות

אלה הם רק חלק מסוגי היישומים הניידים שאנו עובדים איתם, ולכל אחד מהם עשויים להיות מאפיינים ופונקציונליות ספציפיים משלו, המותאמים לצרכים ולמטרות הספציפיות של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 1734 השירותים
הגירת סכמת מסד נתונים של Room באנדרואיד
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית מובייל עבור FEEDME
    פיתוח אפליקציית מובייל עבור FEEDME
    971
  • פיתוח אפליקציית מובייל עבור XOOMER
    פיתוח אפליקציית מובייל עבור XOOMER
    869
  • פיתוח אפליקציית מובייל עבור RHL
    פיתוח אפליקציית מובייל עבור RHL
    1289
  • פיתוח אפליקציית מובייל עבור ZIPPY
    פיתוח אפליקציית מובייל עבור ZIPPY
    1143
  • פיתוח אפליקציית מובייל עבור Affhome
    פיתוח אפליקציית מובייל עבור Affhome
    1076
  • פיתוח אפליקציית מובייל עבור חברת FLAVORS
    פיתוח אפליקציית מובייל עבור חברת FLAVORS
    677

עדכנת את האפליקציה, ובהפעלה הראשונה אתה רואה מסך לבן או קריסה. ב-Logcat: IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. או גרוע מכך: Migration didn't properly handle עם אובדן של כל הנתונים המקומיים. זהו יישום שגוי קלאסי של מיגרציית Room. לצוות שלנו יש ניסיון של 7+ שנים בפיתוח אנדרואיד ולמעלה מ-30 פרויקטים עם מיגרציות ברמות מורכבות שונות. אנחנו עוזרים להימנע ממצבים כאלה. מאמר זה מכסה כיצד לבצע כראוי מיגרציית סכמת מסד נתונים של Room, סוגי שינויים ובדיקות.

לפי הניסיון שלנו, כ-30% מהפרויקטים נתקלים בשגיאות מיגרציה המובילות לאובדן נתונים. בדיקות בזמן מפחיתות סיכון זה ב-80%. מיגרציה נכונה חוסכת עד 50% מזמן הניפוי. למעשה, למעלה מ-90% מפרויקטי המיגרציה שלנו מסתיימים ללא אובדן נתונים, הודות לפרוטוקולי בדיקה קפדניים.

מיגרציית Room: כיצד להימנע משגיאות?

כיצד Room קובע את הצורך במיגרציה?

Room מאחסן hash של סכמת מסד הנתונים. בכל הפעלה, הוא משווה את ה-hash של @Database המהודר עם ה-hash המאוחסן ב-room_master_table. אם הם לא תואמים, Room זורק חריגה אלא אם כן נמצאה מיגרציה מתאימה. ה-version ב-@Database הוא חוזה: אם הסכמה השתנתה, יש להגדיל את הגרסה, ולהוסיף Migration(fromVersion, toVersion) מפורש. תיעוד Room מנהל גרסאות אוטומטית, אך רק עם מעברים מתוארים כראוי.

סוגי שינויים והמיגרציה שלהם

הוספת עמודה (מקרה פשוט)

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE transactions ADD COLUMN category TEXT NOT NULL DEFAULT ''")
    }
}

val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(db: SupportSQLiteDatabase) { db.execSQL("ALTER TABLE transactions ADD COLUMN category TEXT NOT NULL DEFAULT ''") } } הוא חובה. SQLite אינו מאפשר הוספת עמודת NOT NULL ללא DEFAULT לטבלה קיימת עם נתונים.

שינוי שם עמודה

SQLite אינו תומך ב-NOT NULL DEFAULT '' עד גרסה 3.25.0. באנדרואיד API < 29, זה לא זמין. הגישה האוניברסלית היא יצירת טבלה מחדש:

val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("""
            CREATE TABLE transactions_new (
                id TEXT NOT NULL PRIMARY KEY,
                amount REAL NOT NULL,
                description TEXT NOT NULL DEFAULT '',
                created_at INTEGER NOT NULL
            )
        """)
        db.execSQL("""
            INSERT INTO transactions_new (id, amount, description, created_at)
            SELECT id, amount, note, created_at FROM transactions
        """)
        db.execSQL("DROP TABLE transactions")
        db.execSQL("ALTER TABLE transactions_new RENAME TO transactions")
    }
}

הוספת טבלה עם מפתח זר

צור טבלאות באמצעות ALTER TABLE RENAME COLUMN. מפתחות זרים מופעלים לאחר סיום המיגרציה — Room מנהל foreign_keys אוטומטית.

מהן שרשראות מיגרציה וכיצד להשתמש בהן?

Room יכול להחיל מיגרציות ברצף. אם משתמש קופץ מגרסה 1 ל-4, Room יבצע MIGRATION_1_2, לאחר מכן MIGRATION_2_3, ולאחר מכן MIGRATION_3_4 — בתנאי שכולן רשומות.

Room.databaseBuilder(context, AppDatabase::class.java, "app.db")
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4)
    .build()

כדי לזרז, ניתן להוסיף Migration(1,4) ישיר שמבצע את כל השינויים במעבר אחד.

בדיקת מיגרציות עם MigrationTestHelper

כל מיגרציה חייבת להיבדק. Room מספק val MIGRATION_2_3 = object : Migration(2, 3) { override fun migrate(db: SupportSQLiteDatabase) { db.execSQL(""" CREATE TABLE transactions_new ( id TEXT NOT NULL PRIMARY KEY, amount REAL NOT NULL, description TEXT NOT NULL DEFAULT '', created_at INTEGER NOT NULL ) """) db.execSQL(""" INSERT INTO transactions_new (id, amount, description, created_at) SELECT id, amount, note, created_at FROM transactions """) db.execSQL("DROP TABLE transactions") db.execSQL("ALTER TABLE transactions_new RENAME TO transactions") } } עבור JUnit. הכלי מאיץ את האימות עד פי 10 מהר יותר מבדיקה ידנית. דוגמה למיגרציה 1→2:

@RunWith(AndroidJUnit4::class)
class MigrationTest {
    @get:Rule
    val helper = MigrationTestHelper(
        InstrumentationRegistry.getInstrumentation(),
        AppDatabase::class.java
    )

    @Test
    fun migrate1To2() {
        helper.createDatabase(TEST_DB, 1).apply {
            execSQL("INSERT INTO transactions VALUES ('id1', 100.0, 'test', 1700000000)")
            close()
        }

        val db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2)
        val cursor = db.query("SELECT category FROM transactions WHERE id = 'id1'")
        assertTrue(cursor.moveToFirst())
        assertEquals("", cursor.getString(0))
    }
}

ללא בדיקות, אתה מסתכן באובדן נתוני משתמש. אנו מבטיחים שכל מיגרציה נבדקת – הבטחה המגובה בניסיון של 7+ שנים ובמומחיות אנדרואיד מוסמכת.

ייצוא סכמות JSON לאימות

הוסף את ההערה ב-CREATE TABLE IF NOT EXISTS:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
}

Room יוצר Room.databaseBuilder(context, AppDatabase::class.java, "app.db") .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) .build() , MigrationTestHelper — תמונות מצב של הסכמה של כל גרסה. קבצים אלה חייבים להיות מחויבים למאגר. בלעדיהם, @RunWith(AndroidJUnit4::class) class MigrationTest { @get:Rule val helper = MigrationTestHelper( InstrumentationRegistry.getInstrumentation(), AppDatabase::class.java ) @Test fun migrate1To2() { helper.createDatabase(TEST_DB, 1).apply { execSQL("INSERT INTO transactions VALUES ('id1', 100.0, 'test', 1700000000)") close() } val db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2) val cursor = db.query("SELECT category FROM transactions WHERE id = 'id1'") assertTrue(cursor.moveToFirst()) assertEquals("", cursor.getString(0)) } } אינו יכול לאמת מיגרציות.

סוג שינוי תיאור סיכון לאובדן נתונים בדיקה נדרשת
הוספת עמודה ALTER TABLE ADD COLUMN נמוך כן
שינוי שם עמודה יצירת טבלה מחדש בינוני חובה
הוספת טבלה CREATE TABLE נמוך כן
מחיקת עמודה יצירת טבלה מחדש גבוה חובה
מיגרציה הרסנית Database.delete() מלא לא (לא לייצור)

השוואת אסטרטגיות מיגרציה

אסטרטגיה מהירות אמינות מורכבות
ALTER TABLE ADD COLUMN מיידית גבוהה נמוכה
יצירת טבלה מחדש בינונית גבוהה בינונית
מיגרציה הרסנית מיידית נמוכה אפס

כיצד להימנע מאובדן נתונים במהלך מיגרציה?

בדוק תמיד כל מיגרציה על נתונים אמיתיים או סינתטיים. השתמש במערך מלא של מקרים: טבלאות ריקות, רשומות עם NULL, כפילויות. ודא אינדקסים וטריגרים לאחר המיגרציה. בנוסף, אנו ממליצים ליצור גיבוי לפני העדכון.

נפילה למיגרציה הרסנית

כמוצא אחרון — רק עבור build של דיבוג או עם הסכמת משתמש מפורשת: build.gradle מוחק את כל הנתונים. בייצור, זה לא מקובל.

מיגרציית סכמת Room: הגדרה שלב אחר שלב

  1. זהה שינויי סכמה והגדל גרסה ב-android { defaultConfig { javaCompileOptions { annotationProcessorOptions { arguments += ["room.schemaLocation": "$projectDir/schemas".toString()] } } } } .
  2. כתוב אובייקט Migration עם פקודות SQL.
  3. רשום את המיגרציה ב-schemas/1.json.
  4. הגדר ייצוא סכמת JSON ב-build.gradle.
  5. צור בדיקת JUnit עם MigrationTestHelper.
  6. הרץ את הבדיקה וודא תקינות.

מה כלול בשירות המיגרציה שלנו

  • ביקורת מלאה של סכמת מסד הנתונים
  • קוד מיגרציה לכל הגרסאות
  • מערך בדיקות מקיף באמצעות MigrationTestHelper
  • הגדרת ייצוא סכמת JSON
  • תיעוד ומסירה
  • תמיכה לאחר מיגרציה למשך חודש

תמחור

שירותי המיגרציה שלנו מתחילים מ-$500 למיגרציות פשוטות (למשל, הוספת עמודה) ויכולים להגיע עד $2000 לשינוי מבני מורכב הכולל טבלאות מרובות ומפתחות זרים. פרויקטים טיפוסיים נעים בטווח של $800–$1500.

מה העבודה שלנו כוללת

  • ביקורת של הסכמה הנוכחית והיסטוריית גרסאות
  • כתיבת אובייקטי Migration לכל השינויים
  • בדיקות באמצעות MigrationTestHelper לכל מיגרציה
  • הגדרת ייצוא סכמת JSON
  • טיפול במקרי קצה: טבלאות ריקות, מפתחות זרים, אינדקסים, טריגרים

במהלך 7+ השנים האחרונות, השלמנו יותר מ-50 פרויקטי מיגרציה עם אחוז הצלחה של 100% – ללא אובדן נתונים מעולם. מפתחי האנדרואיד המוסמכים שלנו פועלים לפי שיטות העבודה המומלצות בתעשייה כדי להבטיח מעבר חלק.

לוחות זמנים

1–2 מיגרציות פשוטות (הוספת עמודות): 0.5–1 יום. שינוי מבני מורכב עם כיסוי בדיקות מלא: 2–3 ימים. העלות מחושבת באופן אישי — צור קשר להערכה. קבל ביקורת מסד נתונים מפורטת היום.