2010-07-02 5 views
33

SQLiteOpenHelperonUpgrade 메서드가 호출 되었습니까? 그렇다면 언제 전화가 걸려? 개발자가 호출하지 않으면 왜 그곳에 있습니까? 그 기능이 실제로 어떻게됩니까? 나는 모든 테이블을 삭제하는 예제를 보았지만, 모든 테이블을 삭제하는 것은 당신이해야하는 것이 아니라는 주석이 있습니다. 어떤 제안?onUpgrade 메서드가 호출 되었습니까?

답변

20

열린 데이터베이스의 버전보다 새로운 버전으로 SQLiteOpenHelper를 생성 할 때 호출됩니다. 수행 할 작업은 이전 버전과 새 버전간에 변경된 데이터베이스의 변경 사항에 따라 다릅니다. 변경된 테이블을 삭제하지 않는 유일한 경우는 변경 내용이 추가 된 열 이상임을 알리는 경우입니다. 그런 다음 ALTER TABLE.을 사용하여 새 C 럼을 테이블 특성에 추가 할 수 있습니다.

+4

변경 사항은 새 테이블을 추가하는 경우도 있습니다.이 경우 기존 테이블을 삭제하지 않을 수도 있습니다. – CommonsWare

+3

하지만 미리 테이블을 수정한다는 것을 어떻게 알았습니까? 또는 업데이트를 게시 할 때마다 메소드를 변경하면됩니다. –

+3

데이터베이스를 변경하고 onUpgrade에서 다른 사례를 추가 할 때를 알고 있습니다. 따라서 사용자가 응용 프로그램을 업데이트하면 SQLiteOpenHelper는 기존 데이터베이스가 더 이상 사용되지 않으며 해당 작업을 수행한다는 것을 알고 있습니다. 참조 용 Android 소스를 확인하십시오. 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를 사용하는 경우 DB 버전을 변경할 때마다 onUpgrade가 호출됩니다. 이 작업을 수행하려면 추가 요구 사항이 있습니다. db 이름은 동일하게 유지되어야합니다.

콘텐츠 공급자의 onCreate에서 이러한 매개 변수를 사용하는 SQLiteOpenHelper의 인스턴스를 만듭니다. 귀하의 SQLiteOpenHelper 구현과 같을 것이다 : onUpgrade()가 호출 될 때 정확한 순간을 알고 싶은 분들을 위해

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

감사합니다 !!! 이제 마지막으로 onUpgrade를 사용하는 방법을 이해했습니다 :-) – marlar

+0

@ dev.serghini DB 버전 이름을 변경하면 onUpgrade 만 트리거한다는 정보를 어디서 발견 했습니까? 이 문제에 대한 공식적인 확인이 필요하며이 메서드의 공식 java 문서에서는 찾을 수 없습니다. – sandalone

+2

그럼 새로운 질문이 생깁니다 : 언제 "dbVersion"이 변경 되었습니까? 개발자가 제어합니까? 앱의 "appVersion"과 같은가? – sports

36

를, 그것은 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 ...에() 게시물을 모두 검토하고 내가 전화하기 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

실제로 onUpgrade는 getWriteableDatabase()를 호출하는 경우에만 호출됩니다. –

+0

이 설명에 감사드립니다. –

+1

@DoctororDrive - 또한 getReadableDatabase()에서 호출되었습니다. 둘 다''getDatabaseLocked (boolean writable)' – CJBS

4

. Android에 심각한 결함이 있다고 생각하기 시작했습니다.

이 페이지의 정보를 통해 최종 결정을 내릴 수있었습니다. 모든 공헌자들에게 감사드립니다! 이 나를 위해 그것을 해결

...

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 호출 결과 않습니다. 이것들이 나의 필요에 맞는 법안이기 때문에 나는 다른 방법을 확인하지 않았다. 내가 마지막으로 DB 버전이 내 디버깅하는 동안 업데이트 된 것을 깨달았을 때

보관할 읽기, 키커오고있다 ... 내 초기 활동에

이 코드는 ... 우를 알려준!

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

참고 : DatabaseHelper 생성자를 호출하는 생성자 호출 후 DB 버전

를 업데이트 DB를이 새 버전에 태그되었습니다. getWritableDatabase() 또는 getReadableDatabase()를 호출하기 전에 앱을 종료하면 새 버전을 사용할 수 있습니다. 이후 DATABASE_VERSION이 다시 증가 할 때까지 새로운 실행은 onUpgrade 메소드를 호출하지 않습니다. (한숨을 내 자! 이제 무척이나 분명해 보입니다. :)

제 제안은 앱의 초기 단계에 일종의 "checkDatabaseVersion()"을 추가하는 것입니다. 또는 SQLiteOpenHelper 객체를 만드는 경우 응용 프로그램이 종료되기 전에 getWritableDatabase(), getReadableDatabase() 등의 메서드 중 하나를 호출해야합니다.

다른 누군가에게 동일한 머리 긁기를 저장하기를 바랍니다. .. 다음 SqliteOpenHelper 소스 코드를 들여다 보면 p는

2

, 우리는 onCreate(), onUpgrade()onDowngradegetWritableDatabase() 또는 getReadableDatabase() 방법으로 전화를받을 알 수 있습니다. 당신이 getReadableDatabase 또는 getWritableDatabase를 호출 할 때

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

그것은 실제로라고합니다.

깊은 다이빙 :

당신은 mNewVersion라는 변수에 저장됩니다 SQLiteOpenHelper의 생성자에서 버전 번호를 전달합니다. 그게 전부 야. 이 시점에서 아무 일도 일어나지 않습니다.

getReadableDatabase 또는 getWritableDatabase를 호출 할 때마다 getDatabaseLocked이라는 메서드가 호출됩니다. 이 방법은 데이터베이스의 기존 버전 번호를 가져와 mNewVersion과 비교합니다.

  1. 지정된 이름의 데이터베이스가 새 버전이 onUpgrade를 호출 이전 버전보다 큰 경우는 onCreate
  2. 를 호출 존재하지 않습니다.
  3. 새 버전이 기존 버전보다 낮 으면 예외가 발생합니다.
  4. 동일하면 데이터베이스를 엽니 다.

onCreate 및 onUpgrade에 무엇을 써야하나요?

onCreate에는 스키마를 처음 만드는 코드가 있어야합니다.

onUpgrade은 처음 호출되지 않으므로 처음 비워 둘 수 있습니다. 나중 단계에서 테이블 구조를 변경하려면 해당 코드를 여기에 입력해야합니다.

SQLiteOpenHelper.java (소스 코드)

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); 
} 
관련 문제