java - Room 不会自动创建 json 模式文件

标签 java android sqlite android-room

我有一个可以与 SQLite 数据库配合使用的应用程序。我想升级到 Room,我关注了 thisthis用于测试和从 SQLite 升级到 Room 的文章。

我已经创建了EntitiesDAODatabase 类。

以下是我的(build.gradle:app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "APP ID"
        minSdkVersion 20
        targetSdkVersion 28
        versionCode 10
        versionName "1.4.5"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }




    }
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    repositories {
        maven {
            url 'http://dl.bintray.com/amulyakhare/maven'
        }
    }

}

dependencies {
    def room_version = "1.1.1"
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // Core library
    androidTestImplementation 'androidx.test:core:1.0.0'



    androidTestImplementation "androidx.test.ext:junit:1.0.0"
    androidTestImplementation 'androidx.test:rules:1.1.0'

    androidTestImplementation 'android.arch.persistence.room:testing:1.1.1'
    implementation "androidx.room:room-runtime:2.1.0-alpha03"



     implementation "androidx.appcompat:appcompat:1.0.2"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
    implementation 'com.googlecode.libphonenumber:libphonenumber:8.8.1'
    implementation 'com.facebook.stetho:stetho:1.5.0'
    implementation 'com.google.android.material:material:1.1.0-alpha01'
    implementation 'com.hbb20:ccp:2.0.3'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.google.firebase:firebase-ads:11.4.2'
    implementation 'com.google.firebase:firebase-crash:11.4.2'


}

以下是创建数据库副本的测试类

public class SqliteTestDbOpenHelper extends SQLiteOpenHelper {

    public static final int DATABASE_VERSION = 10;

    public SqliteTestDbOpenHelper(Context context, String databaseName) {
        super(context, databaseName, null, DATABASE_VERSION);
    }

    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE  " + ContactsDBContract.ContactsTable.TABLE_CONTACTS +
                "(" +
                ContactsDBContract.ContactsTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
                ContactsDBContract.ContactsTable.CONTACT_ID + " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_LOOKUP_KEY + " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_MESSAGE+ " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_NAME+ " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_PHONE_NUMBER + " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_DATA_VERSION+ " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_STAMP_STATUS+ " TEXT, " +
                ContactsDBContract.ContactsTable.CONTACT_MIMETYPE+ " TEXT, " +
                ContactsDBContract.ContactsTable.IS_BLOCK+ " INTEGER " +

                ")";
       String  CREATE_BLOCK_TABLE = "CREATE TABLE  " + ContactsDBContract.BlockTable.TABLE_BLOCKS +
                "(" +
                ContactsDBContract.BlockTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
                ContactsDBContract.BlockTable.BLOCK_CONTACT_PHONE_NUMBER + " TEXT, " +
                ContactsDBContract.BlockTable.BLOCK_CONTACT_NAME+ " TEXT " +



                ")";
         String CREATE_SCHEDULE_TABLE="CREATE TABLE  " + ContactsDBContract.ScheduleTable.SCHEDULE_TABLE +
                "(" +
                ContactsDBContract.ScheduleTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
                ContactsDBContract.ScheduleTable.SCHEDULE_START_TIME + " TEXT, " +
                ContactsDBContract.ScheduleTable.SCHEDULE_END_TIME+ " TEXT " +



                ")";

        try {
            db.execSQL(CREATE_BLOCK_TABLE);
            db.execSQL(CREATE_CONTACTS_TABLE);
            db.execSQL(CREATE_SCHEDULE_TABLE);
        } catch (SQLException e) {
            e.printStackTrace();
            FirebaseCrash.report(e);
        }
    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Not required as at version 1
    }

    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Not required as at version 1
    }
}

下面是我的房间数据库类

@Database(entities = {ContactsData.class,SchedulesData.class,BlocksData.class}, version = 11,exportSchema = true)
public abstract class DatabaseManager extends RoomDatabase {
    private DatabaseManager database;
    public abstract ContactDao contactsDao();
    public abstract SchedulesDao schedulesDao();
    public abstract BlocksDao blocksDao();

    @VisibleForTesting
    public static Migration MIGRATION_10_11 = new Migration(10,11) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            // nothing to do because we did not change anything
        }
    };

    public DatabaseManager getInstance(Context context){
        if(database == null){
            database = Room.databaseBuilder(context.getApplicationContext(),DatabaseManager.class,"ContactsDB,db")
                    .addMigrations(MIGRATION_10_11).build();
        }
        return database;
    }
}

下面是我的迁移测试类

 @RunWith(AndroidJUnit4.class)
    public class MigrationTest {

        private static final String TEST_DB_NAME = "Contactsdb";
        // Helper for creating Room databases and migrations
        @Rule
        public MigrationTestHelper mMigrationTestHelper =
                new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
                       DatabaseManager.class.getCanonicalName(),
                        new FrameworkSQLiteOpenHelperFactory());

        // Helper for creating SQLite database in version 1
        private SqliteTestDbOpenHelper mSqliteTestDbHelper;

        @Before
        public void setUp() throws Exception {
            // To test migrations from version 1 of the database, we need to create the database
            // with version 1 using SQLite API
            mSqliteTestDbHelper = new SqliteTestDbOpenHelper(ApplicationProvider.getApplicationContext(),
                    TEST_DB_NAME);
            // We're creating the table for every test, to ensure that the table is in the correct state
            SqliteDatabaseTestHelper.createTable(mSqliteTestDbHelper);
        }

        @After
        public void tearDown() throws Exception {
            // Clear the database after every test
            SqliteDatabaseTestHelper.clearDatabase(mSqliteTestDbHelper);
        }

        @Test
        public void migrationFrom1To2_containsCorrectData() throws IOException {
            // Create the database with the initial version 1 schema and insert a user
        SqliteDatabaseTestHelper.addContact(mSqliteTestDbHelper);
            // Create the database with the initial version 1 schema and insert a user
            //SqliteDatabaseTestHelper.insertContact(1, "zaid", mSqliteTestDbHelper);

            mMigrationTestHelper.runMigrationsAndValidate(TEST_DB_NAME, 11, true,
                    MIGRATION_10_11);
            // Get the latest, migrated, version of the database
            DatabaseManager latestDb = getMigratedRoomDatabase();

            // Check that the correct data is in the database
            List<ContactsData> dbUser = latestDb.contactsDao().getAll();
            assertThat(dbUser.size(),is(1));

        }

        @Test
        public void startInVersion2_containsCorrectData() throws IOException {
            // Create the database with version 2
            SupportSQLiteDatabase db = mMigrationTestHelper.createDatabase(TEST_DB_NAME, 3);
            // db has schema version 2. insert some data
            insertContact(db);
            db.close();

            // open the db with Room
            DatabaseManager usersDatabase = getMigratedRoomDatabase();

            // verify that the data is correct
            // Get the latest, migrated, version of the database
            DatabaseManager latestDb = getMigratedRoomDatabase();

            // Check that the correct data is in the database
            List<ContactsData> dbUser = latestDb.contactsDao().getAll();
            assertThat(dbUser.size(),is(1));

        }

        private DatabaseManager getMigratedRoomDatabase() {
            DatabaseManager database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
                    DatabaseManager.class, TEST_DB_NAME)
                    .addMigrations(MIGRATION_10_11)
                    .build();
            // close the database and release any stream resources when the test finishes
            mMigrationTestHelper.closeWhenFinished(database);
            return database;
        }

        private void insertContact(SupportSQLiteDatabase db) {

            ContentValues cv=new ContentValues();
            cv.put(ContactsDBContract.ContactsTable.CONTACT_ID,"212222");
            cv.put(ContactsDBContract.ContactsTable.CONTACT_NAME,"Moti");
            cv.put(ContactsDBContract.ContactsTable.CONTACT_LOOKUP_KEY,"Okay-uuss");
            cv.put(ContactsDBContract.ContactsTable.CONTACT_PHONE_NUMBER,"03215467845");

            db.insert(ContactsDBContract.ContactsTable.TABLE_CONTACTS, SQLiteDatabase.CONFLICT_REPLACE, cv);
        }
    }

但是当我运行/调试 migrationFrom1To2_containsCorrectData() 测试时。我收到以下错误

Cannot find the schema file in the assets folder. Make sure to include the exported json schemas in your test assert inputs. See https://developer.android.com/topic/libraries/architecture/room.html#db-migration-testing for details. Missing file: package.dummy.manager.DatabaseManager/11.json

按照官方文档中的解释,似乎没有在编译时创建模式。可能是我理解有误

最佳答案

这个技巧的目的如下:

在应用模块的应用 build.gradle 文件中添加以下定义:

android {
       ………      
   defaultConfig {
       ………

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

//      *** For Kotlin **** 
//       kapt {
//          arguments {
//              arg("room.schemaLocation", "$projectDir/schemas".toString())
//          
//       }
   }

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin

关于java - Room 不会自动创建 json 模式文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53780092/

相关文章:

android - 我想知道 Android 本身在什么情况下会杀死您的应用程序?

android - 公开不那么 secret 的 oauth key 有哪些风险?有什么解决方法吗?

iphone - 无法在 ios 上打开 sqlite 数据库

sqlite - 如何在 Flutter 应用程序中将 SQLite 数据导出到 CSV 文件

java - 如何解决 MVEL 中包含浮点值的表达式?

java - 同一 servlet URL 的多个 URL 映射产生错误

java - 将多个 Assets 上传到 DAM 会扰乱工作流程步骤

java - 无法再编译 Vaadin 项目(无法执行 objective-c om.vaadin :vaadin-maven-plugin )

android - 房间插入 "one-to-many"关系

c++ - sqlite3_prepare_v2 返回错误 1 ​​代码