Kotlin Exposed操作PostgreSQL时表名被小写,如何使用大写表名?
问题根源
PostgreSQL 默认会将未用双引号包裹的标识符(表名、列名等)自动转换为小写,而 Kotlin Exposed 的默认命名策略不会给标识符添加引号,这就导致你定义的大写表名"Table"在生成 SQL 时被转成了小写的table,数据库自然找不到对应的关系表,从而抛出PSQLException: ERROR: relation "..."。
解决方案
这里提供两种可行的解决方式,你可以根据自己的项目场景选择:
方式一:全局配置带引号的命名策略
如果你的项目中有多个大写表/列需要处理,推荐全局自定义一个命名策略,让 Exposed 生成 SQL 时自动给标识符添加双引号:
// 自定义带引号的命名策略 object QuotedNamingStrategy : DefaultNamingStrategy() { override fun tableName(table: String): String = "\"$table\"" override fun columnName(column: String): String = "\"$column\"" } // 在初始化数据库连接后、执行事务前配置该策略 fun main() { Database.connect("jdbc:postgresql://...", driver = "org.postgresql.Driver") // 应用自定义命名策略 TransactionManager.defaultDatabase.apply { defaultLocale = Locale.ROOT namingStrategy = QuotedNamingStrategy } transaction { logger.addLogger(StdOutSqlLogger) val query = Table.select { Table.id eq 5 } query.forEach { println(it[Table.tC]) } } }
方式二:单独给表/列指定带引号的名称
如果只是个别表需要使用大写名称,可以直接在定义实体类时,给表名和列名包裹双引号:
// 表名和列名直接用双引号包裹 object Table : IntIdTable("\"Table\"") { val tC = text("\"Text\"") val vC = text("\"Value\"") } // 后续的数据库操作代码保持不变 fun main() { Database.connect("jdbc:postgresql://...", driver = "org.postgresql.Driver") transaction { logger.addLogger(StdOutSqlLogger) val query = Table.select { Table.id eq 5 } query.forEach { println(it[Table.tC]) } } }
原理说明
PostgreSQL 对标识符的大小写敏感规则是:
未加双引号的标识符会被自动转为小写;加双引号的标识符会严格保留原始大小写(包括大小写敏感匹配)。
Exposed 默认的DefaultNamingStrategy只是直接返回传入的名称,不会添加引号,所以才会出现大写名称被转成小写的问题。通过上述两种方式让标识符带上双引号,就能让 PostgreSQL 正确识别你的大写表和列了。
内容的提问来源于stack exchange,提问作者Halcyon
相关产品推荐
相关产品推荐

