如何避免kotlin上的N+1查询问题已公开。(当通过DAO的Reference.id.value字段获取值时)
我在Kotlin JVM项目上用作O/R映射器。 版本:0.17.6 当我从Exposed的引用方法定义的DAOAPI列中获取外键列的值时,我遇到了N+1查询问题 我用一个变通代码解决了这个问题,但是有人知道正确的解决方案吗 情况是这样的 有两个表users,user_addresses和一个tableuser_addresses表在otheruser表上有一个外键引用如何避免kotlin上的N+1查询问题已公开。(当通过DAO的Reference.id.value字段获取值时),kotlin,kotlin-exposed,Kotlin,Kotlin Exposed,我在Kotlin JVM项目上用作O/R映射器。 版本:0.17.6 当我从Exposed的引用方法定义的DAOAPI列中获取外键列的值时,我遇到了N+1查询问题 我用一个变通代码解决了这个问题,但是有人知道正确的解决方案吗 情况是这样的 有两个表users,user_addresses和一个tableuser_addresses表在otheruser表上有一个外键引用 object Users : LongIdTable("users") { val name = varchar("n
object Users : LongIdTable("users") {
val name = varchar("name", 30)
}
class User(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<User>(Users)
var name by Users.name
}
object UserAddresses : LongIdTable("user_addresses") {
val user = reference("user_id", Users)
val address = varchar("address", 30)
}
class UserAddress(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<UserAddress>(UserAddresses)
var user by User.referencedOn(UserAddresses.user)
var address by UserAddresses.address
fun toRow(): UserAddressRow {
return UserAddressRow(
id.value,
user.id.value,
address
)
}
}
data class UserAddressRow(val id: Long, val userId: Long, val address: String)
测试数据
INSERT INTO users (id, name) VALUES (1, 'A');
INSERT INTO users (id, name) VALUES (2, 'B');
INSERT INTO user_addresses (user_id, address) VALUES (1, 'X');
INSERT INTO user_addresses (user_id, address) VALUES (1, 'Y');
INSERT INTO user_addresses (user_id, address) VALUES (2, 'Z');
SQL查询日志公开调试日志
[] 2019-11-22 10:41:55.656 [main] DEBUG [cid- uid--] Exposed - SELECT user_addresses.id, user_addresses.user_id, user_addresses.address FROM user_addresses
[] 2019-11-22 10:41:55.668 [main] DEBUG [cid- uid--] Exposed - SELECT users.id, users."name" FROM users WHERE users.id = 1
[] 2019-11-22 10:41:55.670 [main] DEBUG [cid- uid--] Exposed - SELECT users.id, users."name" FROM users WHERE users.id = 2
如果我使用readValue而不是user.id,问题就解决了。
我不确定这个变通方法是否正确。请帮帮我
fun toRow(): UserAddressRow {
return UserAddressRow(
id.value,
readValues[UserAddressTable.user].value,
address
)
}
我注意到下面的简单模式会更好
//Define userId column in DAO (UserAddress class), and use it
class UserAddress(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<UserAddress>(UserAddresses)
var user by User.referencedOn(UserAddresses.user)
var userId by UserAddresses.user
var address by UserAddresses.address
fun toRow(): UserAddressRow {
return UserAddressRow(
id.value,
userId.value,
address
)
}
}
//There is only one SQL statement executed
//SELECT user_addresses.id, user_addresses.user_id, user_addresses.address FROM user_addresses
请查看此处的文档,谢谢您的建议!!这是一次伟大的学习。但实际上,在这种情况下,一些无用的SQL是在使用渴望加载时执行的。这里是细节。急切加载代码:UserAddress.all.withUserAddress::user。已执行无用SQL:从1、1、2中的users.id所在的users中选择users.id、users.name。不需要从users表中选择,所以我只想执行用于查询user\u addresses表。
//Define userId column in DAO (UserAddress class), and use it
class UserAddress(id: EntityID<Long>) : LongEntity(id) {
companion object : LongEntityClass<UserAddress>(UserAddresses)
var user by User.referencedOn(UserAddresses.user)
var userId by UserAddresses.user
var address by UserAddresses.address
fun toRow(): UserAddressRow {
return UserAddressRow(
id.value,
userId.value,
address
)
}
}
//There is only one SQL statement executed
//SELECT user_addresses.id, user_addresses.user_id, user_addresses.address FROM user_addresses