0

我正在将 Postgres 列的类型从UUID更改TEXT

ALTER TABLE my_table ALTER COLUMN id TYPE TEXT;

但我想确保我的代码适用于两种列类型。即因为很难将数据库的更改与在服务器上运行的代码同步。

我正在通过在类型之间切换来进行本地测试。这可以通过移回 UUID 来完成(当数据格式正确时)

ALTER TABLE my_table ALTER COLUMN id TYPE UUID USING id::uuid;

这行得通。但是当切换到 aTEXT并运行我的 Java 代码时,我注意到测试中有一些失败。特别是当一个WHERE语句使用switched时id。例如

UPDATE my_table SET name = 'new_name' WHERE id = '00000000-0000-0000-0001-000000000000'::uuid;

生成

ERROR:  operator does not exist: text = uuid

这对我来说很有意义,因为namedParameterJdbcTemplate我正在使用的类是::uuid在 SQL 查询的 id 末尾添加一个。我不确定它为什么要这样做,但可以通过将传入的参数从 UUID 转换为字符串来解决它。

但是,如果我将列切换回UUID我会收到以下错误

UPDATE my_table SET name = 'new_name' WHERE id = '00000000-0000-0000-0001-000000000000';

生成

ERROR:  operator does not exist: text = uuid

我可以接受导致问题的第一个更新查询,因为我可以在psql命令行上运行它并得到相同的错误。然而,这不会发生在第二个命令中psql

此外,如果我停止使用namedParameterJdbcTemplate's 参数并将值烘焙到 sql 字符串中,它就可以工作。

String sqlStatement = "UPDATE my_table SET name = :v_new_name WHERE id = :v_id";

MapSqlParameterSource sqlParameterMap = new MapSqlParameterSource();
sqlParameterMap.addValue("v_new_name", "New Name");
sqlParameterMap.addValue("v_id", id.toString());

namedParameterJdbcTemplate.update(sqlStatement, sqlParameterMap);

生成

错误:运算符不存在:uuid = 字符变化

SQLStateSQLExceptionTranslator.java.

相对

String sqlStatement = "UPDATE my_table SET name = 'New Name' WHERE id = '" + id.toString() + "'";

MapSqlParameterSource sqlParameterMap = new MapSqlParameterSource();

namedParameterJdbcTemplate.update(sqlStatement, sqlParameterMap);

哪个有效。

为什么会这样?感觉就像在做namedParameterJdbcTemplate一些我找不到的额外类型检查。

4

1 回答 1

0

对必须将变量烘焙到 SQL 语句中的想法感到沮丧,我猜测并尝试了以下操作

String sqlStatement = "UPDATE my_table SET name = :v_new_name WHERE id = :v_id";

MapSqlParameterSource sqlParameterMap = new MapSqlParameterSource();
sqlParameterMap.addValue("v_new_name", "New Name");
sqlParameterMap.addValue("v_id", id.toString(), java.sql.Types.OTHER);

namedParameterJdbcTemplate.update(sqlStatement, sqlParameterMap);

令我惊讶的是,它奏效了。Types.BINARY在我尝试过和之间的差异之前Types.VARCHAR。但我想我需要不那么具体。其他状态的定义

Java 编程语言中的常量,指示 SQL 类型是特定于数据库的,并映射到可以通过 getObject 和 setObject 方法访问的 Java 对象。

这听起来像是一个合适的默认值,但似乎库并没有这样使用它。

我必须注意,这只适用于id.toString(). 单独使用id会导致类型错误。

感谢@a_horse_with_no_name 提供的一些帮助。

于 2020-07-20T16:12:05.583 回答