minivac
01/06/2025, 6:10 PMclass AccountEntity {
... stuff
val users by UserEntity referrersOn UserTable.accountID
with a reference to another entity UserEntity
when queried like
AccountEntity.findById(account.id)!!.load(AccountEntity::users)
works fine, but accessing the users outside of the transaction fails with No transaction in Context
error.
keepLoadedReferencesOutOfTransaction = true
is enabled
Actually forcing the read by doing a map or any other operation makes it actually load and keep it outside the transaction
AccountEntity.findById(account.id)!!.users.map{it}
exposed version 0.57.0, also happening in 0.56.0Oleg Babichev
01/14/2025, 12:50 PMobject UserTable : IntIdTable() {
val name = text("name")
val account = reference("account", AccountTable.id)
}
class EUser(id: EntityID<Int>) : IntEntity(id) {
var name by UserTable.name
var account by EAccount referencedOn UserTable.account
companion object : IntEntityClass<EUser>(UserTable)
}
object AccountTable : IntIdTable() {
val name = text("name")
}
class EAccount(id: EntityID<Int>) : IntEntity(id) {
var name by AccountTable.name
val users by EUser referrersOn UserTable.account
companion object : IntEntityClass<EAccount>(AccountTable)
}
@Test
fun testEntityOutOfTheTransaction() {
var outerAccount: EAccount? = null
withDb(configure = {
keepLoadedReferencesOutOfTransaction = true
}) {
val entityId = inTopLevelTransaction(db.config.defaultIsolationLevel) {
SchemaUtils.create(AccountTable, UserTable)
val accountEntity = EAccount.new { name = "Account1" }
EUser.new {
name = "User1"
account = accountEntity
}
EUser.new {
name = "User2"
account = accountEntity
}
accountEntity.id
}
outerAccount = inTopLevelTransaction(db.config.defaultIsolationLevel) {
EAccount[entityId].load(EAccount::users)
}
}
assertEquals("Account1", outerAccount?.name)
val users = outerAccount?.users?.map { it.name }?.sorted()
assertEquals(2, users?.size)
assertEquals("User1", users!![0])
assertEquals("User2", users[1])
}
When I put keepLoadedReferencesOutOfTransaction
to true
the test is green, in the case of false
it's red.
From the transaction I return only EAccount[entityId].load(EAccount::users)
without extra reads, and save it to the variable out of transaction, and try to read the values for asserts.
Have I understood your idea correct? Probably I missed something, I'd be happy to know about it and try to make the test that reproduces the problem.minivac
01/14/2025, 1:16 PMminivac
01/14/2025, 1:17 PM