Ich verwende Room als Datenbank für die App. Ich habe ein Szenario, in dem eine Object
eines bestimmten Typs in separaten Tabellen gespeichert werden muss. Nehmen wir als Beispiel die Object
mit dem Namen Book.Java
Nun möchte ich zwei SQL-Tabellen haben:
ignorieren Sie bitte alle Namenskonventionen für SQL DB - dies ist nur ein Beispiel
Problem
Normalerweise würde man nur @Entity(tableName = "Books_Read")
in der Book.Java
-Klasse verwenden und eine DAO
-Klasse haben, die diesen Tabellennamen verwenden wird.
Die Sache ist; Wie kann ich dann dieselbe Book.Java
-Klasse zum Speichern in der Books_To_Read
-Tabelle verwenden? Da ich @Entity(tableName = "Books_Read")
bereits als Teil der Book.Java
-Klasse definiert habe, sehe ich keinen Ort, an dem die Books_To_Read
-Tabelle für die Book.Java
-Klasse definiert wird
Die einzige Lösung, die mir einfiel, was ein bisschen Hacker und Unnessasery zu sein scheint, war, eine neue Klasse zu erstellen - nennen wir sie BookToRead.Java
, die Book.Java
erweitert und @Entity(tableName = "Books_To_Read")
in der Klasse definiert.
Frage
Gibt es einen besseren Weg, oder ist dies der erwartete Weg, um damit umzugehen?
Ist dies der erwartete Weg, damit umzugehen?
Nein. Es ist ein falscher Ansatz. Sie sollten Verdoppeln von Daten vermeiden aus mehreren Gründen.
Das kostet Speicherplatz. Mit zunehmender Größe der Datenbank begann sich dieser Wille zu verschlechtern.
Das System wird dadurch kompliziert. Wenn Sie ein einzelnes Feld aktualisieren, müssen Sie möglicherweise dieselbe Aktion an verschiedenen Stellen ausführen. Wenn Sie eines davon vermissen, werden die gesamten Daten zu Inkonsistent. Es ist möglich, Operationen als Einer einzelnen Transaktion auszuführen. Es ist jedoch immer besser, die Datenbankstruktur sauber zu halten.
Methode 1: Neue Tabellen einführen
Sie können Details zu Büchern nur in einer Tabelle speichern, beispielsweise "Books"
. "Books_To_Read"
oder eine andere Tabelle sollte nur den Verweis auf die "Books"
-Tabelle enthalten (Durch Verwendung der ID/des Primärschlüssels in "Books"
-Tabelle). Sie können dann das Schlüsselwort JOIN
verwenden, um den gesamten Datensatz bei einer einzelnen Abfrage abzurufen.
Diese Methode wird bevorzugt, wenn jeder Typ (in diesem Fall gelesene und ungelesene Bücher) über eigene Felder verfügt (Wie das read_date, read_time für gelesene Bücher und wish_to_read für ungelesene Bücher).
Methode 2: Neues Feld einführen
Sie können einfach einen neuen Typ hinzufügen, der den Typ angibt. In diesem Fall gibt es nur zwei Typen (gelesen und ungelesen), ein boolesches Feld (etwa is_read
) ist in Ordnung.
Dies wäre die einfachste Methode. Dies funktioniert jedoch nur, wenn Sie nur angeben möchten, zu welchem Typ die Zeile gehört. Wenn Sie typspezifische Daten speichern müssen und Sie zusätzliche Felder für diesen Zweck hinzufügen, müssen Sie beachten, dass diese Felder auch für andere Typen vorhanden sind.
So habe ich schließlich dieses Problem gelöst:
Ich habe der Book.Java
-Klasse eine ID hinzugefügt, die angibt, ob sie gelesen wurde oder nicht. Gestützt durch eine EnumType
, die entweder book_read
oder book_unread
war, und dann in meiner DAO
für "BooksDataTable"
benutze ich einfach einen SQL query
, um select
die ID
ich möchte. Durch das Ändern der Abfrage kann ich also entweder alle books_read
oder books_to_read
oder all_books
abrufen. Auf diese Weise gibt es keine Duplizierung von Daten und alles befindet sich in einer Tabelle, ohne JOIN
- oder OneToMany
-Beziehungen verwenden zu müssen.
@OneToMany(mappedBy="book_id")
private Set<Book> book
Ich denke, das ist der beste Weg, um zwei Tische miteinander zu verbinden. Probieren Sie es aus und teilen Sie mir Ihre Feedback. Ich werde eine andere Lösung geben
Ich schrieb eine Beispiel-App, als Ahamad seine Antwort gab.
Room stellt eine Abstraktionsschicht über SQLite bereit, um fließend zu ermöglichen Datenbankzugriff bei gleichzeitiger Nutzung der vollen Leistungsfähigkeit von SQLite.
die Hauptidee ist die gleiche wie von Buchdaten in einer Tabelle zu speichern und die ID des Buches in anderen Tabellen zu verwenden. schau dir mein Beispiel project an
ergebnis von logcat
02-19 16:39:26.741 10520-10520/com.example.jingged.roomtest E/MainActivity: Book{id = 1 name = Book 0, author Author 0}
02-19 16:39:26.741 10520-10520/com.example.jingged.roomtest E/MainActivity: Book{id = 2 name = Book 1, author Author 1}
02-19 16:39:26.741 10520-10520/com.example.jingged.roomtest E/MainActivity: Book{id = 3 name = Book 2, author Author 2}
02-19 16:39:26.741 10520-10520/com.example.jingged.roomtest E/MainActivity: Book{id = 4 name = Book 3, author Author 3}
02-19 16:39:26.767 10520-10520/com.example.jingged.roomtest E/MainActivity: BookToRead Book{id = 3 name = Book 2, author Author 2}
02-19 16:39:26.767 10520-10520/com.example.jingged.roomtest E/MainActivity: BookToRead Book{id = 4 name = Book 3, author Author 3}
02-19 16:39:26.768 10520-10520/com.example.jingged.roomtest E/MainActivity: BooksRead Book{id = 1 name = Book 0, author Author 0}
02-19 16:39:26.768 10520-10520/com.example.jingged.roomtest E/MainActivity: BooksRead Book{id = 2 name = Book 1, author Author 1}