Ich möchte Room mit einer vorab ausgefüllten Datenbank verwenden, kann jedoch nicht verstehen, wie Room mitgeteilt werden soll, wo sich meine Datenbank befindet.
Ich habe es jetzt eingefügt src/main/assets/databases
und wenn ich die Instanz für die Raumdatenbank erstelle, erstelle ich es folgendermaßen:
Room.databaseBuilder(
getApplicationContext(),
AppDatabase.class,
"justintrain.db"
)
.allowMainThreadQueries()
.build();
Auf diese Weise wird meiner Meinung nach jedes Mal eine neue Datenbank erstellt, oder es wird sowieso nicht die vorab ausgefüllte Datenbank verwendet.
Wie kann ich meine Datenbank finden?
android
android-sqlite
android-room
Alberto Giunta
quelle
quelle
getDatabasePath()
für den von Ihnen gewählten Datenbankdateinamen gespeichert wird . Vereinbaren Sie dann, dass das Asset in diesen Pfad kopiert wird, bevor Sie das erstellenRoomDatabase
, falls diese Datei noch nicht vorhanden ist. Dies ist die erste Option, die ich in dieser Ausgabe vorschlage. Im Idealfall haben wir mehr Sicherheit, dass "getDatabasePath()
für den von Ihnen gewählten Datenbankdateinamen" die richtige Antwort ist.Antworten:
So habe ich es gelöst und wie Sie Ihre Anwendung mit einer vorab ausgefüllten Datenbank versenden können (bis zu Room v. Alpha5)
Legen Sie Ihre SQLite-Datenbank
database_name.db
in denassets/databases
OrdnerNehmen Sie die Dateien aus diesem Repo und legen Sie sie in ein Paket namens dh
sqlAsset
AppDatabase
Ändern Sie in Ihrer Klasse den DB-Erstellungscode Ihres Raums entsprechend:Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db") .openHelperFactory(new AssetSQLiteOpenHelperFactory()) .allowMainThreadQueries() .build();
Beachten Sie, dass Sie
"database_name.db"
und nichtgetDatabasePath()
oder andere Methoden verwenden müssen: Es wird nur der Name der Datei benötigt.quelle
AutoClosable
), kann dies jedoch nicht mit Beta1 tun (SupportSQLiteOpenHelper.Configuration
einigeAssetSQLiteOpenHelper
UPDATE (7. November 2019)
Room unterstützt jetzt die Verwendung einer vorgefertigten Datenbank ab Version 2.2.0
https://developer.android.com/jetpack/androidx/releases/room#2.2.0
Lösung vor Version 2.2.0: Einfache Lösung ohne andere externe Bibliotheken.
Room verwendet den vorhandenen Android-Framework-Code, um eine Datenbank zu erstellen oder zu öffnen. Wenn Sie sich den Quellcode von
FrameworkSQLiteOpenHelper
(Room's Version vonSQLiteOpenHelper
) ansehen, werden intern interneSQLiteOpenHelper.getReadableDatabase()
Methoden und andere Methoden aufgerufen, wo immer dies erforderlich ist.Die einfachste Lösung besteht also darin, die DB-Datei einfach aus dem Assets-Verzeichnis zu kopieren,
mContext.getDatabasePath("my-database.sqlite")
bevor Sie die DB mit Room erstellen.In Ihrem Fall sieht der Code ungefähr so aus -
private final String DB_NAME = "my-database.sqlite"; private MyDatabase buildDatabase(Context context) { final File dbFile = context.getDatabasePath(DB_NAME); if(!dbFile.exists()) { copyDatabaseFile(dbFile.getAbsolutePath()); } return Room.databaseBuilder(context.getApplicationContext(), MyDatabase.class, DB_NAME) .build(); } private void copyDatabaseFile(String destinationPath) { // code to copy the file from assets/database directory to destinationPath }
Dieser Link enthält den Code, der zum Kopieren des DB- Links mit Code benötigt wird
quelle
Ich hatte das gleiche Problem und habe eine Bibliothek erstellt, die genau das tut. Die akzeptierte Antwort funktioniert, aber ich denke, es ist einfacher, eine Bibliothek zu benutzen.
AppDatabase db = RoomAsset .databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db") .build();
Fügen Sie es am Ende der Repositorys zu Ihrem root build.gradle hinzu:
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
Fügen Sie die Abhängigkeit hinzu
dependencies { // ... other dependencies implementation 'com.github.humazed:RoomAsset:v1.0' }
Sie finden die Bibliothek hier: https://github.com/humazed/RoomAsset
quelle
Context.deleteDatabase()
in der Anwendung, wenn die Anwendung aktualisiert wurde.room.schemaLocation
Annotation Processor-Argument angeben oder exportSchema auf false setzen.Funktionierende 2019-Lösung ohne Hacks oder Abhängigkeiten (Kotlin)
Platzieren Sie Ihre
.db
Datei inassets/databases
(oder wirklich in einem beliebigen Ordner, solange es sich darunter befindetassets
).Verwenden Sie die vorhandene
createFromAsset()
Funktion von Raum 2.2 und übergeben Sie den Pfad zur Datenbank. Wenn Ihre Datenbankdatei beispielsweise benannt istmy_data.db
und sich imdatabases
Verzeichnis desassets
Ordners befindet, würden Sie dies tuncreateFromAsset("databases/my_data.db")
.Angenommen, Ihr Datenbankname (z. B.
my_data
) ist in einer konstanten Variablen mit dem Namen gespeichertDATABASE_NAME
, können Sie diesen Beispielcode verwenden:Room.databaseBuilder( context.applicationContext, MyDatabase::class.java, DATABASE_NAME ) .createFromAsset("databases/$DATABASE_NAME.db") .build()
Wichtig : Stellen Sie sicher, dass das Schema Ihrer Datenklasse / Entität genau mit dem Schema Ihrer
.db
Datei übereinstimmt . Wenn eine Spalte beispielsweise nicht explizit alsNOT NULL
in der.db
Datei markiert ist, bedeutet dies, dass die Spalte Nullwerte enthalten kann. In Kotlin müssten Sie dies mitval colName: dataType? = null
in Ihrer Datenklasse abgleichen. Wenn Sie dies nur tunval colName: dataType
, kompiliert Kotlin dies zu einerNOT NULL
Spalte und löst eine Ausnahme aus, wenn Sie versuchen, Ihre App auszuführen.Hinweis : Wenn Sie stattdessen eine Raumdatenbank aus einer Datenbankdatei erstellen möchten, die Sie auf das Android-Gerät selbst herunterladen, können Sie die
createFromFile()
Funktion alternativ verwenden . Lesen Sie dazu die offizielle Dokumentation .quelle
Room unterstützt jetzt Prepopulated Databases. Bereiten Sie Ihre Datenbank einfach mit Programmen wie SQLite Browser oder einem anderen Programm vor . Dann legen Sie es
Assets Folder
wahrscheinlich in einem Unterordner namensdatabase
then call:Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db") .createFromAsset("database/myapp.db") .build()
Wenn Sie Ihre Datenbank nicht als Asset bereitgestellt, sondern heruntergeladen oder im Dateisystem gespeichert haben, lautet die Methode wie folgt:
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db") .createFromFile(File("mypath")) .build()
Weitere Beschreibungen oder Datenbankmigrationen zu dieser Funktion finden Sie im Dokumentationstraining .
quelle
Ähnliche Lösung mit Raum ohne Verwendung externer Bibliotheken: 1. Kopieren Sie Ihre Datenbank in den Assets-Ordner. 2. Kopieren Sie Ihre Datenbank aus dem Assets-Ordner
public class MainActivity extends AppCompatActivity { public static AppDatabase db; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); copyDatabase(getApplicationContext(), "yourdatabase.db"); db = Room.databaseBuilder(getApplicationContext(), .class, "yourdatabase.db").allowMainThreadQueries().build(); } private void copyDatabase(Context context, String databaseName) { final File dbPath = context.getDatabasePath(databaseName); // If the database already exists, return if (dbPath.exists()) { Log.d("Activity", "db Path Exists"); return; } // Make sure we have a path to the file dbPath.getParentFile().mkdirs(); // Try to copy database file try { final InputStream inputStream = context.getAssets().open(databaseName); final OutputStream output = new FileOutputStream(dbPath); byte[] buffer = new byte[8192]; int length; while ((length = inputStream.read(buffer, 0, 8192)) > 0) { output.write(buffer, 0, length); } output.flush(); output.close(); inputStream.close(); } catch (IOException e) { Log.d("Activity", "Failed to open file", e); e.printStackTrace(); } }
}}
quelle
Ab Raum 2.2 können Sie Ihre Datenbank mit dem folgenden Befehl vorab füllen:
Room.databaseBuilder(appContext, TestDatabase.class, “Sample.db”) .createFromAsset(“database/myapp.db”) .build()
quelle
Sie kopieren Sie einfach
assets/databases
aufapp/databases
und als Add
addMigrations()
indatabaseBuilder
sie Ihre Daten halten
quelle