簡體   English   中英

從 SQLite 遷移到 Room DB

[英]Migration from SQLite to Room DB

我從 SQLite 遷移到 Room DB 時遇到問題。

The problem is my old SQLite schema doesn't match with the new Room DB schema in my old SQLite DB I forgot to set primaryKey to NOT NULL and also I have a column URL and that column doesn't have any type like TEXT, INTEGER或 BOOLEAN。

因此,現在當我嘗試將 SQLite 遷移到 Room 時,出現 Schema 不匹配錯誤,並且我的應用程序使用 SQLite DB 在 Play 商店中發布。

因此,我們將不勝感激任何幫助。

我的舊 SQLite 數據庫代碼:

private static final String DATABASE_NAME = "mylist.db";
private static final String TABLE_NAME = "mylist_data";
private static final String POST_TITLE = "ITEM1";
private static final String POST_URL = "URL";
private static final String KEY_ID = "ID";


public BookmarksDb(Context context) {
    super(context, DATABASE_NAME, null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {
    String createTable = "CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
            " ITEM1 TEXT," +
            " URL)";

    db.execSQL(createTable);
}

我的新房間數據庫代碼:

@Entity(tableName = "mylist_data")
public class Bookmark {
@PrimaryKey()
@ColumnInfo(name = "ID")
private int id;

@ColumnInfo(name = "ITEM1")
private String postTitle;

@ColumnInfo(name = "URL")
private String postUrl;

問題是:

  1. ID 不是 NULL = false 在 SQLite 中,在 Room 中默認為 true(無法更改)
  2. SQLite 中的 URL 列沒有任何類型,在 Room 中默認為 TEXT。

我不想丟失存儲在 SQLite 中的舊數據並且我的應用程序已發布,所以現在我想在不丟失舊用戶數據的情況下遷移到 Room。

請幫我解決這個問題。

你有兩個問題,第一個 NOT NULL 是由於 Room 如何處理原語。 所以不要使用int使用Integer (雖然你真的應該使用 Long)。 因此,將實體更改為:-

@Entity(tableName = "mylist_data")
public class Bookmark {
@PrimaryKey()
@ColumnInfo(name = "ID")
private Integer id;

@ColumnInfo(name = "ITEM1")
private String postTitle;

@ColumnInfo(name = "URL")
private String postUrl;

第二個問題是列關聯,您需要更改表以適應實體,因為您有private String postUrl; 那么正如您所發現的那樣,Room 需要一個 TEXT 列類型,而不是什么都沒有(未定義的 Affinity = 1)。

為了避免這種情況,您可以運行以下 SQL 將表轉換為適合 Room:-

DROP TABLE IF EXISTS converted_mylist_data;
DROP TABLE IF EXISTS old_mylist_data; 
CREATE TABLE IF NOT EXISTS converted_mylist_data (ID INTEGER PRIMARY KEY AUTOINCREMENT, ITEM1 TEXT, URL TEXT);
INSERT INTO converted_mylist_data SELECT * FROM mylist_data; /* copies existing data into new table */
ALTER TABLE mylist_data RENAME TO old_mylist_data;
ALTER TABLE converted_mylist_data RENAME TO mylist_data;
DROP TABLE IF EXISTS old_mylist_data;
  • 請注意,您實際上可以檢索 SQL 以從 java(生成)創建新表

例子

運行 1 使用以下命令創建不使用 Room 的數據庫(版本 1):-

db.execSQL("CREATE TABLE mylist_data (ID INTEGER PRIMARY KEY AUTOINCREMENT,ITEM1 TEXT, URL);");
db.execSQL("INSERT INTO mylist_data VALUES(null,'item1','my url');");

在此處輸入圖像描述

然后進行以下更改:-

  1. 添加了實體

:-

@Entity(tableName = "mylist_data")
public class Bookmark {
    @PrimaryKey()
    @ColumnInfo(name = "ID")
    private Long id; /* <<<<<<<<<< CHANGED (could be Integer) from primative to object*/

    @ColumnInfo(name = "ITEM1")
    private String postTitle;

    @ColumnInfo(name = "URL")
    private String postUrl;

    public Bookmark(){}

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPostTitle() {
        return postTitle;
    }

    public void setPostTitle(String postTitle) {
        this.postTitle = postTitle;
    }

    public String getPostUrl() {
        return postUrl;
    }

    public void setPostUrl(String postUrl) {
        this.postUrl = postUrl;
    }
}
  1. 阿道

:-

@Dao
interface AllDao {
    @Query("SELECT * FROM mylist_data")
    List<Bookmark> getAll();
}
  1. 版本增加的數據庫和版本 1 到 2 的遷移

:-

@Database(entities = Bookmark.class,version = 2 /*<<<<<<<<<<*/,exportSchema = false)
abstract class TheDatabase extends RoomDatabase {
    abstract AllDao getAllDao();    
    private static volatile TheDatabase instance;

    public static TheDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context,TheDatabase.class,"mylist.db")
                    .allowMainThreadQueries()
                    .addMigrations(MIGRATION_1_2)
                    .build();
        }
        return instance;
    }

    static final Migration MIGRATION_1_2 = new Migration(1,2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {

            database.beginTransaction();
            database.execSQL("DROP TABLE IF EXISTS converted_mylist_data;");
            database.execSQL("DROP TABLE IF EXISTS oldmylist_data;");
            database.execSQL("CREATE TABLE IF NOT EXISTS converted_mylist_data (ID INTEGER PRIMARY KEY AUTOINCREMENT, ITEM1 TEXT, URL TEXT);");
            database.execSQL("INSERT INTO converted_mylist_data SELECT * FROM mylist_data;");
            database.execSQL("ALTER TABLE mylist_data RENAME TO oldmylist_data;");
            database.execSQL("ALTER TABLE main.converted_mylist_data RENAME TO mylist_data;");
            database.setTransactionSuccessful();
            database.endTransaction();

        }
    };
}
  1. 更改的調用/使用活動(從 SQLite 到已注釋掉舊代碼的 Room)

:-

public class MainActivity extends AppCompatActivity {

    //DBHelper db; /* Run 1 */
    TheDatabase db; /* Run 2  NEW */
    AllDao dao; /* Run 2  NEW */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /* Run 1 create the SQLite based database */
        /*
        db = new DBHelper(this);
        db.getWritableDatabase();
         */
        /* Run 2  NEW */
        db = TheDatabase.getInstance(this);
        dao = db.getAllDao();
        for (Bookmark b: dao.getAll()) {
            Log.d("BOOKMARKINFO","ID = " + b.getId() + " PostTitle = " + b.getPostTitle() + " PostURL =" + b.getPostUrl());
        }
    }
}

結果:-

成功運行並輸出:-

D/BOOKMARKINFO: ID = 1 PostTitle = item1 PostURL =my url

即數據已被保留。

默認情況下 sqlite 如果在 create table 語句中未定義類型,則使用 Blob 列類型。 sqlite doc 的第 3.1.3段。 這就是為什么您可以使用 @ColumnInfo(name = "URL", typeAffinity = ColumnInfo.BLOB) 來解決您的第二個問題。 你用int類型聲明 id 不能是 null,嘗試使用Integer代替int - 我認為它解決了你的第一個問題。

我認為您還有其他選擇可以在房間遷移而不丟失數據: 使用遷移機制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM