如何使用Jetbrains Exposed实现分片表的Union查询?
解决Jetbrains Exposed Union查询循环累积失效问题
问题根源
你的代码存在两个核心问题:
- Union方法返回值未正确赋值:Exposed的
union()方法不会修改原Query对象,而是返回包含Union逻辑的新Query实例。之前的代码仅调用finalQuery.union(query)却未将结果存回finalQuery,导致每次循环都丢弃了Union后的新查询。 - 分片表映射错误:代码中始终复用同一个
Model类执行selectAll(),这意味着所有查询都指向同一张表,而非预期的不同分片表。
修正方案
第一步:定义分片表的Table映射
创建可动态指定表名的Table子类,用于映射不同分片表:
class ShardedTable(tableName: String) : Table(tableName) { // 按实际表结构定义列,示例如下: val id = integer("id") val name = varchar("name", 50) // 补充其他列定义 }
第二步:正确累积Union查询
通过重新赋值finalQuery保存每次Union后的结果,同时为每个分片表创建独立的Table实例:
fun main() { val tableNames = listOf("table_1", "table_2", "table_3") var finalQuery: Query? = null for (tableName in tableNames) { // 为每个分片表创建独立的Table实例 val shardedTable = ShardedTable(tableName) val currentQuery = shardedTable.selectAll() finalQuery = if (finalQuery == null) { currentQuery } else { // 关键:将Union后的新Query赋值回finalQuery finalQuery.union(currentQuery) } } // 执行并打印结果 finalQuery?.let { println(it.toList()) } ?: println("没有可合并的查询") }
更简洁的写法(使用fold函数)
用Kotlin的fold函数简化累积逻辑,避免显式null判断:
fun main() { val tableNames = listOf("table_1", "table_2", "table_3") // 生成所有分片表的查询 val allQueries = tableNames.map { ShardedTable(it).selectAll() } // 累积Union查询 val finalQuery = allQueries.fold(null as Query?) { acc, query -> acc?.union(query) ?: query } finalQuery?.let { println(it.toList()) } }
关键注意事项
- 每个分片表必须对应独立的
ShardedTable实例,否则所有查询都会指向同一张表。 - 必须保留
union()方法的返回值,因为Exposed的Query采用不可变设计,所有修改操作都会返回新实例。
内容的提问来源于stack exchange,提问作者Subhadip Das Gupta
相关产品推荐
相关产品推荐

