'Room database - get table name at runtime
Suppose I declare my entity like so:
@Entity(tableName = "banana")
data class MyStuff(
@PrimaryKey val id: String
)
When Room KAPT does it's magic, @Entity annotation is stripped so it is no longer there at runtime.
E.g. if I write MyStuff::class.annotations it returns empty list.
If I used @Entity(tableName = "banana") so my table name does NOT match my class name, how can I query Room database to find out that a given entity type means a given table name?
UPDATE
So I found a workaround albeit horrific.
It seems that Room actually has no knowledge about mapping between the Entity and the Table. This information is compiled into the BODY of the DAO.
This is also why they make you use DAOs for all your tables which is very verbose.
Nevertheless, through some other needs I have the following annotation in my project:
@Target(AnnotationTarget.CLASS)
annotation class DaoType(val type: KClass<*>)
I also have a method to getDao from a KClass<*>.
All my DAO objects include an autogenerated deleteAll method like so:
@Delete
fun deleteAll(vararg entities: MyStuff)
Given that, I can get the table name like so:
var tableName: String? = null
val daoType = (entityType.annotations.firstOrNull { it is DaoType } as? DaoType)
?.type
daoType?.let {
val dao = getDao<Any>(it.java)
dao?.let { d ->
val statementFields: List<Field> =
d::class.java.declaredFields.filter { f ->
return@filter f.type.declaredMethods.firstOrNull { m -> m.name == "createQuery" } != null
}
for (field in statementFields) {
field.isAccessible = true
val fieldVal = field.get(d) ?: continue
val method = field.type.declaredMethods.first { m -> m.name == "createQuery" }
val query = method.invoke(fieldVal) as? String ?: continue
if (query.startsWith("DELETE FROM ")) {
var matchResult = "DELETE\\sFROM\\s`(.*?)`.*".toRegex().find(query)
val table = matchResult?.groupValues?.lastOrNull()
if (table != null) {
tableName = table
}
}
}
}
}
Note: I am not marking this an accepted answer because I am not happy about the level of dependency on the inner workings of Room.
Still, this works at least now.
Solution 1:[1]
You could use something like :-
@Entity(tableName = MyStuff.tableName)
data class MyStuff(
@PrimaryKey val id: String
) {
companion object {
const val tableName = "banana"
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MikeT |
