Kotlin Exposed查询PostgreSQL报错:列users.emailSituation不存在
这个报错的核心原因是PostgreSQL对标识符的大小写处理规则:默认情况下,PostgreSQL会把未用双引号包裹的表名、列名自动转换为全小写。而你的Exposed实体中,emailSituation列指定的名称是驼峰式的"emailSituation",但数据库实际存储的列名是自动转换后的emailsituation(全小写),导致查询时找不到对应的列。
下面给你几种可行的解决方法,按推荐程度排序:
方法1:修改Exposed列定义匹配数据库实际列名
如果你的数据库里已经创建了emailsituation这个全小写列,直接修改Exposed中该列的名称定义即可:
object Users : IntIdTable() { val name = text("name").index() val family = text("family").index() val email = text("email").index() // 把列名改为全小写,匹配数据库实际列名 val emailSituation = bool("emailsituation") val mobile = long("mobile").index() }
修改后,Exposed生成的SQL会使用users.emailsituation,和数据库的列名完全匹配,就能解决报错。
方法2:使用命名策略自动转换驼峰为蛇形(推荐)
更规范的做法是遵循Kotlin用驼峰、数据库用蛇形命名的惯例,通过Exposed的命名策略自动处理转换,避免手动指定列名的麻烦:
首先添加一个蛇形转换的工具函数:
fun String.toSnakeCase(): String { return this.replace(Regex("([a-z])([A-Z])"), "$1_$2").lowercase() }
然后在数据库连接初始化后配置全局命名策略:
Database.connect("jdbc:postgresql://localhost:5432/your_db", driver = "org.postgresql.Driver", user = "user", password = "pass") TransactionManager.defaultDatabase.defaultTableNamingStrategy = object : NamingStrategy { override fun tableName(table: Table) = table.name.lowercase() override fun columnName(column: Column<*>) = column.name.toSnakeCase() }
之后你的表定义可以简化,不用手动指定列名,Exposed会自动把驼峰的emailSituation转换为数据库的email_situation:
object Users : IntIdTable() { val name = text().index() // 自动映射为name列 val family = text().index() // 自动映射为family列 val email = text().index() // 自动映射为email列 val emailSituation = bool() // 自动映射为email_situation列 val mobile = long().index() // 自动映射为mobile列 }
这种方式既符合语言和数据库的各自规范,也能从根源上避免大小写不匹配的问题。
方法3:强制使用双引号包裹列名(不推荐)
如果你坚持要在数据库中保留驼峰式的emailSituation列,需要在创建表时用双引号包裹列名(比如CREATE TABLE users ("emailSituation" BOOLEAN)),同时在Exposed的列定义中也用双引号包裹名称:
val emailSituation = bool("\"emailSituation\"")
不过这种方式不推荐,因为PostgreSQL中带双引号的标识符是严格区分大小写的,后续所有操作都必须保持一致,会增加维护成本。
内容的提问来源于stack exchange,提问作者Mohammad Daliri

