web-dev-qa-db-de.com

Mehrere Tabellen mit demselben Objekttyp in der Raumdatenbank

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:

  • Books_Read
  • Bücher zum Lesen 

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? 

18
Robert J. Clegg

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.


Lösung

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.

11
Anees

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. 

1
Robert J. Clegg
@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

0
Muthu

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}
0
Sahil Manchanda