使用 Room 时如何手动调用 CREATE TABLE?

JJD*_*JJD 6 android database-migration create-table kotlin android-room

鉴于SQLiteOpenHelperJava 中的这个习惯:

public class ExamplesOpenHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_NAME = "app.db";

    private static final String CREATE_TABLE_STATEMENT =
            "CREATE TABLE examples (_id INTEGER PRIMARY KEY, NAME TEXT);";

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_STATEMENT);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS examples");
        onCreate(db);
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以CREATE_TABLE_STATEMENT在数据库迁移中引用。onUpgrade()无需复制 SQL 代码。

我想用Kotlin和Room实现相同的功能,如下所示:

@Database(
        entities = [
            (Example::class)
        ],
        version = 2
)
abstract class ExamplesDatabase : RoomDatabase() {

    companion object {

        const val NAME = "examples"

        @Volatile
        private var INSTANCE: ExamplesDatabase? = null

        @JvmStatic
        fun getInstance(context: Context): ExamplesDatabase =
                INSTANCE ?: synchronized(this) {
                    INSTANCE ?: buildDatabase(context).also {
                        INSTANCE = it
                    }
                }

        private fun buildDatabase(context: Context) =
                Room.databaseBuilder(
                        context.applicationContext,
                        ExamplesDatabase::class.java,
                        NAME)
                        .addMigrations(MIGRATION_1_2)
                        .build()

        private val MIGRATION_1_2 = object : Migration(1, 2) {
            override fun migrate(db: SupportSQLiteDatabase) {
                // How to invoke CREATE TABLE here?
            }
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

这次实际的表定义是从Example模型中推断出来的。我如何推断CREATE_TABLE_STATEMENT来自 Room 以便我可以在迁移中使用它?我想避免手动编写语句,从而将其定义两次:一次在模型中,一次在 SQL 语句中。

Jos*_*hua 1

不,我认为没有办法做到这一点。参见官方教程。

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                + "`name` TEXT, PRIMARY KEY(`id`))");
    }
};
Run Code Online (Sandbox Code Playgroud)

看来得自己写了。

  • 这隐式地重复了表定义。一旦“@Entity”模型定义了它。一旦 SQL 语句定义了它。我不想维持这一点。 (5认同)