2010-07-02 11 views
33

onUpgradeSQLiteOpenHelper की विधि कभी भी बुलाया गया है? यदि हां, तो इसे कब कहा जाता है और किसके द्वारा? यदि डेवलपर्स द्वारा इसे नहीं कहा जाता है, तो वहां क्यों है? उस समारोह के साथ वास्तव में क्या होता है? मैंने उदाहरण देखे हैं जहां यह सभी तालिकाओं को छोड़ देता है, लेकिन फिर एक टिप्पणी कहती है कि सभी तालिकाओं को छोड़ना आपको नहीं करना चाहिए। कोई सुझाव?क्या ऑन अपग्रेड विधि कभी कॉल की जाती है?

उत्तर

20

यह तब कहा जाता है जब आप SQLiteOpenHelper को खोले गए डेटाबेस के संस्करण की तुलना में संस्करण के साथ नए बनाते हैं। क्या करना है पुराने और नए संस्करणों के बीच किए गए डेटाबेस में किए गए परिवर्तनों पर निर्भर करता है। एकमात्र मामला जब आप एक बदली हुई तालिका नहीं छोड़ते हैं तब परिवर्तन एक अतिरिक्त कॉलम से अधिक नोट कर रहा है। फिर आप टेबल हस्ताक्षर में नया कॉलम जोड़ने के लिए वैकल्पिक तालिका कथन का उपयोग कर सकते हैं।

+4

परिवर्तन भी नई टेबल, जिस स्थिति में आप किसी भी मौजूदा टेबल नहीं छोड़ सकता जोड़ने जा सकता है। – CommonsWare

+3

लेकिन आप समय से पहले कैसे जानते होंगे कि आप एक टेबल को संशोधित करेंगे? या जब भी आप एक अद्यतन प्रकाशित करते हैं तो आपको बस विधि को बदलना होगा। –

+3

आप जानते हैं कि आप डेटाबेस बदल रहे हैं और अपग्रेड में एक और मामला जोड़ें। तो जब उपयोगकर्ता ऐप को अपडेट करता है, तो SQLiteOpenHelper जानता है कि मौजूदा डेटाबेस अप्रचलित है और अनुसार कार्रवाई करता है। संदर्भ के लिए एंड्रॉयड स्रोत का एक टुकड़ा की जाँच करें: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=packages/SettingsProvider/src/com/android/providers /settings/DatabaseHelper.java – ognian

28

यदि आप SQLiteOpenHelper का उपयोग कर रहे हैं तो ऑन अपग्रेड को जब भी आप डीबी संस्करण बदलते हैं तो कॉल किया जाएगा। इस के लिए काम करने के लिए एक अतिरिक्त आवश्यकता है। डीबी नाम वही रहता है।

Old Version: 
dbName = "mydb.db" 
dbVersion = 1 

New Version: 
dbName = "mydb.db" 
dbVersion = 2 

सामग्री प्रदाता के ऑनक्रेट में आप SQLiteOpenHelper का एक उदाहरण बनाते हैं जो इन पैराम को लेता है। आपका SQLiteOpenHelper कार्यान्वयन इस प्रकार दिखाई देगा:

public static final class MySQLiteOpenHelper extends SQLiteOpenHelper { 

     public MySQLiteOpenHelper(Context context, int dbVersion, String dbName) { 
      super(context, dbName, null, dbVersion); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
      //Code to create your db here 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      // Code to upgrade your db here 
     } 

} 
+0

धन्यवाद !!! अब मैं अंत में समझ गया कि अपग्रेड पर कैसे उपयोग करें :-) – marlar

+0

@ dev.serghini आपको डीबी संस्करण नाम बदलने के बारे में जानकारी कहां मिली है, केवल 'अपग्रेड' को ट्रिगर करें? मुझे इसके लिए आधिकारिक पुष्टि की आवश्यकता है और मैं इसे इस विधि के आधिकारिक जावा दस्तावेज़ों में नहीं ढूंढ सकता। – sandalone

+2

तो फिर एक नया प्रश्न उठता है: "डीबीवीर्सन" कब बदलता है? क्या डेवलपर नियंत्रण करता है? ऐप के "एपवर्सन" की तरह? – sports

36

आप में से जो लोग सही समय जानना चाहते हैं जब onUpgrade() कहा जाता हो जाता है के लिए, यह या तो getReadableDatabase() या getWriteableDatabase() के लिए एक कॉल के दौरान होता है।

उन लोगों के लिए जो स्पष्ट नहीं हैं कि यह कैसे ट्रिगर हो जाता है, जवाब है: यह तब ट्रिगर होता है जब SqLiteOpenHelper के निर्माता को प्रदान किया गया डेटाबेस संस्करण अद्यतन किया जाता है। यहाँ एक उदाहरण

public class dbSchemaHelper extends SQLiteOpenHelper { 

private String sql; 
private final String D_TAG = "FundExpense"; 
//update this to get onUpgrade() method of sqliteopenhelper class called 
static final int DB_VERSION = 2; 
static final String DB_NAME = "fundExpenseManager"; 

public dbSchemaHelper(Context context) { 
    super(context, DB_NAME, null, DB_VERSION); 
    // TODO Auto-generated constructor stub 
} 

अब है ... onUpgrade()

@Override 
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { 
    sql = "ALTER TABLE " + fundExpenseSchema.Expense.TABLE_NAME + " ADD COLUMN " + fundExpenseSchema.Expense.FUNDID + " INTEGER"; 
    arg0.execSQL(sql); 
} 
+2

असल में अपग्रेड केवल तभी कॉल किया जाता है जब आप GetWriteableDatabase() को कॉल करते हैं। –

+0

इस स्पष्टीकरण –

+1

@DoctororDrive के लिए धन्यवाद - यह भी 'getReadableDatabase()' पर कहा जाता है; दोनों 'getDatabaseLocked (बूलियन लिखने योग्य)' – CJBS

4

सभी पोस्ट की समीक्षा करना और डिबग कोड यह अभी भी मेरे लिए स्पष्ट नहीं था जब मैं onUpgrade देखना होगा बुलाया हो रही चल रहा है। मुझे लगता है कि एंड्रॉइड में गंभीर दोष था ..

इस पृष्ठ की जानकारी ने मुझे अपने अंतिम संकल्प का नेतृत्व किया। धन्यवाद सभी योगदानकर्ताओं के लिए एक गुच्छा!

यह मेरे लिए इसे हल ...

public class DatabaseHelper extends SQLiteOpenHelper { 
    public static String TAG = DatabaseHelper.class.getName(); 
    private static final int DATABASE_VERSION = 42; 
    private static final String DATABASE_NAME = "app_database"; 
    private static final String OLD_TABLE = "old_and_useless"; 

    public DatabaseHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     if(newVersion > oldVersion) { 
      Log.d(TAG, "cool! you noticed."); 

      db.execSQL("DROP TABLE IF EXISTS " + OLD_TABLE); 
      // other calls like onCreate if necessary 

     } else { 
      Log.d(TAG, "Hey! didn't you see me?"); 
     } 

    } 

    public void checkDatabaseVersion() { 
     SQLiteDatabase db = this.getWritableDatabase(); 

     // if the DATABASE_VERSION is newer 
     // onUpgrade is called before this is reached 
    } 


    // other code removed for readability... 
} 

यह सच है कि getWritableDatabase() और getReadableDatabase (है) onUpgrade कॉल में परिणाम है। मैंने अन्य तरीकों की जांच नहीं की क्योंकि ये मेरी जरूरतों के लिए बिल फिट बैठते हैं।

रखें पढ़ने, किकर आ रहा है ...

मेरी प्रारंभिक गतिविधि में इस कोड को मुझे प्रबुद्ध जब मैं अंत में एहसास हुआ कि डाटाबेस संस्करण मेरी डीबगिंग के दौरान अद्यतन करने गया था ... ओह!

DatabaseHelper dbHelper = new DatabaseHelper(this); 
dbHelper.checkDatabaseVersion(); 

नोट: DatabaseHelper निर्माता बुला अद्यतन करता है डाटाबेस संस्करण

निर्माता कॉल करने के बाद, डाटाबेस नए संस्करण के साथ टैग किया गया। GetDritableDatabase() या getReadableDatabase() प्राप्त करने के लिए कॉल से पहले ऐप को मारें और आप नए संस्करण पर हैं। उसके बाद नए निष्पादन कभी भी अपग्रेड विधि को कॉल नहीं करते जब तक DATABASE_VERSION फिर से बढ़ता नहीं है। (श्वास! अब यह हास्यास्पद रूप से स्पष्ट लगता है :)

मेरा सुझाव है कि आप अपने ऐप के शुरुआती चरणों में "चेकडेटाबेसवर्सन()" को जोड़ दें। वैकल्पिक रूप से, यदि आप SQLiteOpenHelper ऑब्जेक्ट बनाते हैं तो सुनिश्चित करें कि आप अपने ऐप से पहले एक विधि (getWritableDatabase(), getReadableDatabase() इत्यादि) को कॉल करें ..

मुझे आशा है कि यह किसी और को सिर खरोंच से बचाएगा! ..: p

2

SqliteOpenHelper स्रोत कोड में देख रहे हैं, हम पता कर सकते onCreate(), onUpgrade() और onDowngradegetWritableDatabase() या getReadableDatabase() विधि में कहा जाता है मिलता है।

public SQLiteDatabase getWritableDatabase() { 
    synchronized (this) { 
     return getDatabaseLocked(true); 
    } 
} 
public SQLiteDatabase getReadableDatabase() { 
    synchronized (this) { 
     return getDatabaseLocked(false); 
    } 
} 

private SQLiteDatabase getDatabaseLocked(boolean writable) { 
    if (mDatabase != null) { 
     if (!mDatabase.isOpen()) { 
      // Darn! The user closed the database by calling mDatabase.close(). 
      mDatabase = null; 
     } else if (!writable || !mDatabase.isReadOnly()) { 
      // The database is already open for business. 
      return mDatabase; 
     } 
    } 
      . . . . . . 

     final int version = db.getVersion(); 
     if (version != mNewVersion) { 
      if (db.isReadOnly()) { 
       throw new SQLiteException("Can't upgrade read-only database from version " + 
         db.getVersion() + " to " + mNewVersion + ": " + mName); 
      } 

      db.beginTransaction(); 
      try { 
       if (version == 0) { 
        onCreate(db); 
       } else { 
        if (version > mNewVersion) { 
         onDowngrade(db, version, mNewVersion); 
        } else { 
         onUpgrade(db, version, mNewVersion); 
        } 
       } 
       db.setVersion(mNewVersion); 
       db.setTransactionSuccessful(); 
      } finally { 
       db.endTransaction(); 
      } 
     } 

     onOpen(db); 

     if (db.isReadOnly()) { 
      Log.w(TAG, "Opened " + mName + " in read-only mode"); 
     } 

     mDatabase = db; 
     return db; 
    } finally { 
     mIsInitializing = false; 
     if (db != null && db != mDatabase) { 
      db.close(); 
     } 
    } 
} 
1

यह वास्तव में कहा जाता है जब आप getReadableDatabase या getWritableDatabase कहते हैं।

गहन:

आप SQLiteOpenHelper के निर्माता जो एक चर mNewVersion कहा जाता है में संग्रहीत किया जाता में संस्करण संख्या गुजरती हैं। बस। इस बिंदु पर कुछ भी नहीं होता है।

हर बार जब आप कॉल करते हैं तो रीड करने योग्य डाटाबेस या getWritableDatabase, यह getDatabaseLocked नामक एक विधि को कॉल करेगा। इस विधि को डेटाबेस का मौजूदा संस्करण संख्या मिलेगी और इसकी तुलना mNewVersion से की जाएगी।

  1. दिए गए नाम के साथ डेटाबेस मौजूद नहीं है यह onCreate
  2. फोन करेगा नया संस्करण पुराने संस्करण यह onUpgrade कॉल करेंगे की तुलना में अधिक है।
  3. यदि नया संस्करण मौजूदा संस्करण से कम है, तो एक अपवाद फेंक दिया जाएगा।
  4. यदि वे बराबर हैं तो यह आगे बढ़ेगा और डेटाबेस खोल देगा।

मुझे क्रेते और अपग्रेड पर क्या लिखना चाहिए?

onCreate में कोड होना चाहिए जो पहली बार एक स्कीमा बनाता है।

आप पहली बार onUpgrade खाली छोड़ सकते हैं क्योंकि इसे पहली बार नहीं कहा जाएगा। जब आप बाद के चरण में तालिका संरचना को बदलना चाहते हैं, तो उस कोड को यहां जाना चाहिए।

SQLiteOpenHelper।जावा (स्रोत कोड)

public SQLiteDatabase getWritableDatabase() { 
    synchronized (this) { 
     return getDatabaseLocked(true); 
    } 
} 

public SQLiteDatabase getReadableDatabase() { 
    synchronized (this) { 
     return getDatabaseLocked(false); 
    } 
} 

private SQLiteDatabase getDatabaseLocked(boolean writable) { 
    . 
    . 

    final int version = db.getVersion(); 

     if (version != mNewVersion) { 
      if (db.isReadOnly()) { 
       throw new SQLiteException("Can't upgrade read-only database from version " + 
         db.getVersion() + " to " + mNewVersion + ": " + mName); 
      } 

      db.beginTransaction(); 
      try { 
       if (version == 0) { 
        onCreate(db); 
       } else { 
        if (version > mNewVersion) { 
         onDowngrade(db, version, mNewVersion); 
        } else { 
         onUpgrade(db, version, mNewVersion); 
        } 
       } 
       db.setVersion(mNewVersion); 
       db.setTransactionSuccessful(); 
      } finally { 
       db.endTransaction(); 
      } 
     } 

     onOpen(db); 
} 
संबंधित मुद्दे