minivac
05/09/2024, 5:55 PMreferencedOn
DAO operator, a table declared like this:
object UsersRolesPivotTable(...) {
val userID = nodeID<UserID>("user_id").references(UserTable.id)
val roleID = nodeID<RoleID>("role_id").references(RoleTable.id)
}
class UsersRolesPivotEntity(...) {
...
val role by RoleEntity referencedOn UsersRolesPivotTable.roleID
}
// The nodeID function, just registers a column that is just a typed UUID under the hood
inline fun <reified T : NodeID> Table.nodeID(name: String): Column<T> {
return registerColumn(name, NodeColumnType { T::class.primaryConstructor!!.call(it) })
}
now produces a class cast exception when trying to read the the role
from the entity.
class ai.zylon.backend.core.node.RoleID cannot be cast to class org.jetbrains.exposed.dao.id.EntityID (ai.zylon.backend.core.node.RoleID is in unnamed module of loader io.ktor.server.engine.OverridingClassLoader$ChildURLClassLoader @6999cd39; org.jetbrains.exposed.dao.id.EntityID is in unnamed module of loader 'app')
at org.jetbrains.exposed.sql.EntityIDColumnType.notNullValueToDB(ColumnType.kt:199)
at org.jetbrains.exposed.sql.IColumnType$DefaultImpls.valueToDB(ColumnType.kt:39)
at org.jetbrains.exposed.sql.ColumnType.valueToDB(ColumnType.kt:103)
...
It's trying to cast an ID (in my case a RoleID
) as an EntityID
. This worked fine in 0.49.0
Modifying the table to use just reference
fixes the issue but forces me to change types across the whole application which is quite a big refactor, all the plain T
id types become EntityID<T>
.
object UsersRolesPivotTable(...) {
val userID = references("user_id", UserTable.id)
val roleID = references("role_id", RoleTable.id)
}
So essentially, registerColumn(...).references(...)
breaks the DAO now, reference(...)
works fine.Chantal Loncle
05/09/2024, 9:21 PMregisterColumn().references()
.
To help resolve your issue, please consider giving some more details about:
• What is the signature of NodeColumnType
, particularly what it extends or what ColumnType<?>
is.
• Maybe also what notNullValueToDB()
or valueToDB()
looks like.
• What UserTable
and RoleTable
extend. At minimum, what is the Column<?>
of UserTable.id
, for example: Column<EntityID<UserID>>
?
• The same for NodeID
. Does it implement Comparable
for example?
If you'd prefer to open an issue on YouTrack with a full reproducible example, please feel free to do so as well, so we can assist you further.minivac
05/09/2024, 10:28 PMChantal Loncle
05/09/2024, 11:44 PMminivac
05/10/2024, 9:28 AMtable_a
and table_b
, b has a reference to table_a
and uses val entityA by EntityA referencedOn TableB.refToA
to load it in the EntityB.
object TableA : UUIDTable("table_a")
class EntityA(id: EntityID<UUID>) : UUIDEntity(id) {
companion object : UUIDEntityClass<EntityA>(TableA)
}
object TableB : UUIDTable("table_b") {
val refToA = registerColumn("ref_to_a", UUIDColumnType())
.references(TableA.id)
}
class EntityB(id: EntityID<UUID>) : UUIDEntity(id) {
companion object : UUIDEntityClass<EntityB>(TableB)
var refToA by TableB.refToA
val entityA by EntityA referencedOn TableB.refToA
}
The SQL to load one of each in the database:
CREATE TABLE IF NOT EXISTS table_a
(
id uuid PRIMARY KEY
);
CREATE TABLE IF NOT EXISTS table_b
(
id uuid PRIMARY KEY,
ref_to_a uuid NOT NULL,
CONSTRAINT fk_table_b_ref_to_a__id FOREIGN KEY (ref_to_a) REFERENCES table_a (id) ON DELETE RESTRICT ON UPDATE RESTRICT
);
INSERT INTO table_a (id)
VALUES ('00000000-0000-0000-0000-000000000001');
INSERT INTO table_b (id, ref_to_a)
VALUES ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000001');
The test:
transaction {
val b = EntityB.all().first()
println(b.entityA) // <--- this will fail
}
class java.util.UUID cannot be cast to class org.jetbrains.exposed.dao.id.EntityID (java.util.UUID is in module java.base of loader 'bootstrap'; org.jetbrains.exposed.dao.id.EntityID is in unnamed module of loader 'app')
minivac
05/10/2024, 9:32 AMIntIdTable
, so maybe the bug is on the UUIDTable
stuff, which I am also using in my project 🤔minivac
05/10/2024, 12:02 PMEntity.kt
line 132
else -> {
// @formatter:off
factory.findWithCacheCondition({
reference.referee!!.getValue(this, desc) == refValue
}) {
reference.referee<REF>()!! eq refValue
}.singleOrNull()?.also {
storeReferenceInCache(reference, it)
}
// @formatter:on
}
this reference.referee<REF>()!! eq refValue
expression is used in a find { ... }
,
the reference.referee<REF>()!!
is correct, refValue
is an UUID
also correct.
Crash finally happens when it then reaches ColumnType.kt
EntityIDColumnType<T>::notNullValueToDB
, after the typing update in 0.50.0 the parameter is no longer Any
but EntityID<T>
so the UUID
trying to be cast o an EntityID<UUID>
simply crashesChantal Loncle
05/10/2024, 11:53 PMminivac
05/12/2024, 10:54 PMChantal Loncle
05/13/2024, 2:23 PMminivac
05/16/2024, 8:50 AMChantal Loncle
05/20/2024, 9:20 PM