About preloading .db files, what means this sentence in the room documentation?
Note: Automated Room migrations rely on the generated database schema for both the old and the new versions of the database. If exportSchema is set to false, or if you have not yet compiled the database with the new version number, then automated migrations fail.
Specifically the part on if you have not yet compiled the database with the new version number.
What is refering to? maybe google is telling that we need to open the sqlite file with an external tool and edit the pragma user_version value? Is that mandatory to make room migrations work?
About preloading .db files, what means this sentence in the room documentation?
Note: Automated Room migrations rely on the generated database schema for both the old and the new versions of the database. If exportSchema is set to false, or if you have not yet compiled the database with the new version number, then automated migrations fail.
Specifically the part on if you have not yet compiled the database with the new version number.
What is refering to? maybe google is telling that we need to open the sqlite file with an external tool and edit the pragma user_version value? Is that mandatory to make room migrations work?
Share Improve this question asked Mar 16 at 16:06 NullPointerExceptionNullPointerException 37.8k80 gold badges231 silver badges405 bronze badges1 Answer
Reset to default 0What is refering to?
If you have set exportSchema
to false.
False
indicates that Auto Migrations are not possible.
- This is because when
true
the schemas are stored as part of the package allow Room to look at previous schemas and thus generate the code to alter (migrate) the schema (with limitations). - No stored schema to compare then there is no way, at compile time, that Room can determine what has changed and so no way to Automate the migrations to suit the change from old to new.
It should also be noted that the schema is hashed at compile time and is stored in the actual database in a table called room_master_table, as a single row.
The [Version Number], this is passed/generated at compile time. It is used to compare against the [user_version] in the actual database as part of the header (the header is the1st 100 bytes of the file, the[user_version] is 4 bytes and is access as an integer value).
If there is a mismatch then the value in the database would/should be lower than the compiled version number, this being used to determine the migration(s) to be undertaken. If in the case of exportSchema
being false (i.e. no Auto Migration) AND falbackToDestructiveMigration
has been specified AND there are no migrations to cover the migration then the database is deleted and will be created according to the current schema UNLESS createFromAsset
(File) indicates that the database should be copied from the asset/file after which comparison with the expected current schema and version number are undertaken, any discrepancies being handled according to the rules/code.
part of this is that the code, when the compiled version, conflicts with the
user_version
, results in the copied database (asset/file) being considered incorrect and recoverable by dropping the copied database and proceeding with the empty (correct schema wise) database.With regard to comments asking WHY you are expected to edit/alter the asset/file. If for example you added a table, then the asset/file would need to include that new table otherwise the asset/file would be incorrect. Likewise the version (
user_version
in the asset/file).
Is that mandatory to make room migrations work?
YES the asset/file MUST adhere to what Room expects schema wise (tables/columns etc) and as important user_version
wise.
- Potentially No IF you handle everything (schema change, asset/file handling and user_version change). The prePackagedDatabase callback, which is called after the asset/file has been copied, allowing modifications the be made to the database.
You may find this of interest.
Additional re comment
Is the user_version of the pragma? ¿Is the @Database version= specified in the source code of the app?
The user_version is an SQLite feature that allows an integer value to be stored as part of the actual database. The actual database is a file (actually up to 3 files the additional files being for logging purposes).
- the value can be changed using the user_version pragma. This will change the value in the actual database file.
The Android SQLite API (which Room uses), when opening the database file compares the compiled value passed to the SQLiteOpenHelper (see https://developer.android/reference/android/database/sqlite/SQLiteOpenHelper#SQLiteOpenHelper(android.content.Context,%20java.lang.String,%20android.database.sqlite.SQLiteDatabase.CursorFactory,%20int)).
Room passes this value from the version parameter of the @Database
annotation. The code generated by Room will check this against the actual database file, expecting the values to match.
A mismatch, at least at the SQLiteOpenHelper
level will result in either the onUpgrade
or onDownGrade method
to be called. Room introduces it's own handling supporting the use of Migrations
. The SQliteOpenHelper
also has a feature that will overwrite an existing database file with a new database under some situations, which is effectively what /fallbackToDestructiveMigration
allows. i.e. If there is no migration covering the actual value to compiled value then the database file is overwritten.
If using a pre-packaged database (asset or file), then this IS NOT the actual database rather it is the source of the actual database, it being copied when/if called for (at that time there is no actual database file).
- The pre-packaged database itself CANNOT be changed it is part of the package for the App and is protected.
Hence again, the user_version, as part of the actual database file (which will be sourced from the pre-packaged database asset/file) MUST (in typical scenarios) be what Room expects, as per the version parameter of the @Database
annotation.
- there are ways to divert away from the typical scenario e.g. the linked answer above.
Room in addition to this comparison of the compile and actual version. Also checks the expected (compiled) schema against the schema of the actual database file. The check requires ALL expected core components (the tables) to both exist. Room also expects the columns and column types to exactly match. Room does not care if additional core components exist (so other tables, views, triggers can exist).
When a project is compiled, part of the annotation processing for Room, includes the generation of a HASH based upon the schema, which is based upon the @Entity
annotated lasses that have been defined is being part of the database via the entities
parameter of the @Database
annotation.
You can view this HASH after a successful compilation, as well as how it is applied to the actual database by looking at the project's generated Java, in the class that is named the same as the class(es) that are
@Database
annotated, but suffiex with_Imply
.- e.g. in the
createAllTables
method there would be a line of code likedb.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '13f6238c5604c9bb9b22b806284b1bcc')");
- e.g. in the
As such there are 2 checks undertaken to ensure that the actual database is according to the compiled code, noting that if using a pre-packaged database, that the copy of the file/asset from the package is undertaken before these checks.
I appreciate your detailed answer, but it's very complex to understand, to be honest, I'm now even more confused than before.
Perhaps even more so after another onslaught of details, but as per the comment in the question you asked before this, change the package to adhere to Room's expectations (i.e. set the user_version accordingly before including the database file as part of the package).
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744593752a4582765.html
评论列表(0条)