简体   繁体   English

Room数据库中具有相同类型对象的多个表

[英]Multiple tables with same type of objects in Room database

I'm using Room as the database for the app. 我正在使用Room作为应用程序的数据库。 I have a scenario where an Object of a certain type needs to be stored in separate tables. 我有一个场景,其中某种类型的Object需要存储在单独的表中。 As an example, lets take the Object called Book.java 举个例子,让我们拿一个名为Book.javaObject

Now, I want to have two SQL tables: 现在,我想要两个SQL表:

  • Books_Read Books_Read
  • Books_To_Read Books_To_Read

ignore any naming conventions for SQL DB please - this is just an example 请忽略SQL DB的任何命名约定 - 这只是一个例子

Problem 问题

Normally, one would just use @Entity(tableName = "Books_Read") in the Book.java class and have a DAO class that will use that table name. 通常,人们只会在Book.java类中使用@Entity(tableName = "Books_Read")并拥有一个将使用该表名的DAO类。

The thing is; 事情是; how would I then be able to use the same Book.java class to store in the Books_To_Read table? 那么我怎样才能使用相同的Book.java类存储在Books_To_Read表中? Since I already defined @Entity(tableName = "Books_Read") as part of the Book.java class and I see no where to define the Books_To_Read table for the Book.java class 因为我已经将@Entity(tableName = "Books_Read")Book.java类的一部分,所以我看不到在哪里为Book.java类定义Books_To_Read

The only solution I was able to come up with, which seems a little hackery and unnessasery, was to create a new class - let's call it BookToRead.java that extends Book.java and define @Entity(tableName = "Books_To_Read") in the class. 我能够提出的唯一解决方案是创建一个新类 - 让我们称之为BookToRead.java ,它扩展了Book.java并定义了@Entity(tableName = "Books_To_Read") 。类。

Question

Is there a better way to do this or is this the expected way to handle it? 有没有更好的方法来做到这一点,或者这是处理它的预期方法?

Is this the expected way to handle it? 这是处理它的预期方式吗?

No . It is a wrong approach. 这是一种错误的做法。 You should eliminate duplication of data for several reasons. 出于多种原因,您应该消除重复数据

  • It will cost storage space. 这将耗费存储空间。 As the size of database increases, this will began to become worse. 随着数据库大小的增加,这将开始变得更糟。

  • It will make the system complicated. 它会使系统变得复杂。 If you are updating a single field, You may have to perform the same action at different places. 如果要更新单个字段,则可能必须在不同位置执行相同的操作。 If you miss any one of them, the entire data will become inconsistent. 如果您错过了其中任何一个,整个数据将变得不一致。 It is possible to perform such operations as a single transaction. 可以执行诸如单个事务的操作。 But it is always better to keep the database structure clean. 但是保持数据库结构清洁总是更好。


Solution

Method 1: Introduce new tables 方法1:引入新表

You can store details of books in only one table say "Books" . 您可以只在一个表中存储书籍的详细信息,例如"Books" "Books_To_Read" or any other table should contain only the reference to the "Books" table ( By using the id/ primary key in "Books" table ). "Books_To_Read"或任何其他表应该只包含参照"Books"表( 通过在使用id /主键"Books" )。 You can then use the JOIN keyword to get the entire record at a single query. 然后,您可以使用JOIN关键字在单个查询中获取整个记录。

This method is preferred if each type (read and unread books in this case) has it's own set of fields ( Like the read_date, read_time for read books and wish_to_read for unread books ). 如果每种类型(在这种情况下是读取和未读书籍)都有自己的字段集( 如read_date,read_time用于读取书籍,wish_to_read用于未读书籍则首选此方法。

Method 2: Introduce new field 方法2:引入新领域

You can simply add a new type which specifies the type. 您只需添加一个指定类型的新类型即可。 In this case, there are only two type(read and unread), a boolean field (something like is_read ) will be fine. 在这种情况下,只有两种类型(读取和未读取),布尔字段(类似于is_read )就可以了。

This would be the easiest method. 这将是最简单的方法。 But this will work only if you just want to indicate which type the row belongs to. 但这只有在您只想指出该行所属的类型时才有效。 If you do need to store type specific data and you introduce additional fields for that purpose, remember that those fields will exists for others types too. 如果确实需要存储特定于类型的数据,并为此目的引入了其他字段,请记住这些字段也适用于其他类型。

This is how I eventually solved this problem: 这就是我最终解决这个问题的方法:

I added an ID to the Book.java class that represents whether it has been read or not. 我在Book.java类中添加了一个ID,表示它是否已被读取。 Backed by an EnumType that was either book_read or book_unread and then in my DAO for "BooksDataTable" I then just use a SQL query to select the ID I want. 由一个是book_readbook_unreadEnumType支持,然后在我的DAO"BooksDataTable" ,然后我只使用SQL queryselect我想要的ID So by changing the query I can get either all the books_read or books_to_read or all_books . 因此,通过更改查询,我可以获得所有books_readbooks_to_readall_books This way, there is no duplication of data and everything is in one table, without having to use JOIN or OneToMany relationships. 这样,没有重复的数据,所有内容都在一个表中,而不必使用JOINOneToMany关系。

@OneToMany(mappedBy="book_id")
private Set<Book> book

I think this is best way to connecting two tables. 我认为这是连接两个表的最佳方法。 Try it and let me know your feed back. 尝试一下,让我知道您的反馈。 I will give anothor solution 我会给出一个解决方案

I was writing sample app when Ahamad gave his answer. 当Ahamad给出答案时,我正在编写示例应用程序。

Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. Room提供了一个覆盖SQLite的抽象层,允许流畅的数据库访问,同时利用SQLite的全部功能。

main idea is same as of to store Book data in one table and use the id of the book in other tables. 主要思想与将书籍数据存储在一个表格中相同,并在其他表格中使用书籍的ID。 have a look at my sample project 看看我的示例项目

result of logcat 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}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM