Home > Enterprise >  Can I create multiple tables with one data class?
Can I create multiple tables with one data class?

Time:09-30

What I wanna do is, By merging the following two data classes into one, the two tables are divided as they are.

@Entity(tableName = "file")
    data class File(
    @PrimaryKey
    @ColumnInfo(name = "path") var path: String,
    @ColumnInfo(name = "date", index = true) var date: Long,
    @ColumnInfo(name = "number") var num: Float = -1f
)

@Entity(tableName = "del_file")
    data class delFile(
    @PrimaryKey
    @ColumnInfo(name = "path") var path: String,
    @ColumnInfo(name = "date", index = true) var date: Long,
    @ColumnInfo(name = "number") var num: Float = -1f
)

The reason I want to manage those two tables separately is that they are used in completely different situations. 'file' will be used in the app's file system, and 'del_file' will be managed only in the recycle bin.

I also thought about adding and managing a column called "is_alive" to the "file" table, but I thought it was a bad structure in that it would be meaningless data in almost all entries and that filtering was required for all queries to be used in the app's file system.

The best way I think is to manage each of the two tables, but I thought I couldn't come up with a better way because I wasn't good enough.

Is there a way to manage the table separately while making that data class one? Or is there a better way?

I would be very, very grateful if you could tell me a good way.

CodePudding user response:

Generally, having two separate tables for the same data model is not good because it may lead to data duplication, which has various disadvantages; for example, it costs storage space and data inconsistency, etc.

There are two ways to deal with this situation. If you want to distinguish file items just by one field(for example, is_alive), the best way is to use one table with the is_alive field. You can use this way to solve your problem.

But if those distinguishable fields are more than one or maybe in the future become more, the solution is to create another table(like def_file) that contains only the reference to the original table(file table) and those fields. In other words, to avoiding data duplication, separate those fields in another table with a reference to the original table and then use JOIN when you want to retrieve them.

For more detail see this

CodePudding user response:

You cannot have a single @Entity annotated class for multiple tables.

However, you could use a class as the basis of other classes, by embedding the class into the other classes.

e.g. you could have:-

@Entity(tableName = "file")
    data class File(
    @PrimaryKey
    @ColumnInfo(name = "path") var path: String,
    @ColumnInfo(name = "date", index = true) var date: Long,
    @ColumnInfo(name = "number") var num: Float = -1f
)

and the second class as :-

@Entity(tableName = "del_file",primaryKeys = ["path"], indices = [Index("date")])
data class delFile(
    @Embedded
    val file: File
)

However, you may need to be aware of what is and isn't applied to the class that Embeds another class.

  • You cannot use @ColumnInfo with an @Embedded (it is not necessarily a single column)
  • The @PrimaryKey is lost/dropped when Embedding thus why you would need to define the primary key in the @Entity annotation of the class that Embeds the other class (it is feasible to have multiple @Embeddeds and thus impossible to determine what the correct primary key should be (Room requires that a primary key is defined))
  • Likewise for the index on the date column and hence the indicies being defined in the @Entity of the delFile class that Embeds the other class.
  • However the name given in the @ColumnInfo of the first is used in the second (safe to propogate this).

As an example of the columns names being different than the field/variable name, if, for the first, you had:-

@Entity(tableName = "file")
data class File(
    @PrimaryKey
    @ColumnInfo(name = "mypath") var path: String,
    @ColumnInfo(name = "mydate", index = true) var date: Long,
    @ColumnInfo(name = "mynumber") var num: Float = -1f
)

Then as the column names are different to the field/variable names then you would have to use:-

@Entity(tableName = "del_file",primaryKeys = ["mypath"], indices = [Index("mydate")])
data class delFile(
    @Embedded
    val file: File
)

You would also have to be aware that, changes to the File class would also apply to the delFile class, which could be useful at times but potentially problematic at other times.

Changes to the second (delFile) class would not be applied to the first (File) class, so you would have the freedom to augment the second e.g.

@Entity(tableName = "del_file",primaryKeys = ["mypath"], indices = [Index("mydate")])
data class delFile(
    @Embedded
    val file: File,
    val another_column: String
)

This would result in the del_file table having the additional another_column column.

  • Related