You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Exposed操作MySQL:自定义查询生成调用内置函数可行吗?

在Kotlin Exposed中实现MySQL UUID Binary(16)的查询自定义

当然可以不用完全自定义QueryBuilder,Exposed提供了多种灵活的方式来实现这类自定义查询逻辑,下面是几种实用方案:

方案1:自定义UUID Binary列类型(推荐,自动处理转换)

这种方式可以让列在插入、更新和查询时自动处理UUID与binary(16)的转换,无需每次手动编写函数调用。

import org.jetbrains.exposed.sql.*
import java.util.UUID

class MySqlUUIDBinaryColumn(name: String) : Column<UUID>(name, UUIDColumnType()) {
    override fun appendExpressionToQuery(queryBuilder: QueryBuilder) {
        when (queryBuilder.parent) {
            is UpdateBuilder<*>, is InsertBuilder -> {
                // 插入/更新时,将UUID转为binary(16),调用MySQL的UUID_TO_BIN函数
                queryBuilder.append("UUID_TO_BIN(", this, ", 1)")
            }
            else -> {
                // 查询时,将binary(16)转回UUID,调用MySQL的BIN_TO_UUID函数
                queryBuilder.append("BIN_TO_UUID(", this, ", 1)")
            }
        }
    }

    override fun createColumnOptions(): String {
        return "BINARY(16)"
    }
}

// 扩展Table类,简化该列的创建
fun Table.uuidBinary(name: String): Column<UUID> = registerColumn(name, MySqlUUIDBinaryColumn(name))

// 使用示例
object TestTable : Table("test_table") {
    val id = uuidBinary("id").primaryKey()
    val name = varchar("name", 50)
}

// 查询示例:自动生成带BIN_TO_UUID的条件
val targetUuid = UUID.randomUUID()
val result = TestTable.select { TestTable.id eq targetUuid }.singleOrNull()
// 生成的SQL:SELECT BIN_TO_UUID(test_table.id, 1), test_table.name FROM test_table WHERE BIN_TO_UUID(test_table.id, 1) = ?

方案2:扩展DSL函数,手动构建查询条件

如果不想自定义列类型,可以写一个扩展函数快速生成包含BIN_TO_UUID的查询条件:

import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SqlExpressionBuilder
import java.util.UUID

// 扩展ByteArray类型的列,支持直接与UUID比较
infix fun Column<ByteArray>.eqUuid(uuid: UUID): Op<Boolean> {
    return SqlExpressionBuilder.run {
        FunctionCall("BIN_TO_UUID", listOf(this@eqUuid, 1)) eq uuid.toString()
    }
}

// 使用示例
object TestTable : Table("test_table") {
    val id = binary("id", 16).primaryKey()
    val name = varchar("name", 50)
}

val targetUuid = UUID.randomUUID()
val result = TestTable.select { TestTable.id eqUuid targetUuid }.singleOrNull()
// 生成的SQL:SELECT test_table.id, test_table.name FROM test_table WHERE BIN_TO_UUID(test_table.id, 1) = ?

方案3:自定义BIN_TO_UUID函数类

直接定义对应MySQL内置函数的Exposed Function类,方便在查询中灵活组合使用:

import org.jetbrains.exposed.sql.*
import java.util.UUID

class BinToUuidFunction(column: Column<ByteArray>, flag: Int = 1) : Function<UUID>(UUIDColumnType()) {
    override fun toQueryBuilder(queryBuilder: QueryBuilder) {
        queryBuilder.append("BIN_TO_UUID(", column, ", ", flag, ")")
    }
}

// 使用示例
val targetUuid = UUID.randomUUID()
val result = TestTable.select {
    BinToUuidFunction(TestTable.id) eq targetUuid
}.singleOrNull()
// 生成的SQL与方案2一致

内容的提问来源于stack exchange,提问作者lipsum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:45:22