Ошибка org.postgresql.util.PSQLException: ОШИБКА: оператор не существует: my_enum_type = изменение символа может быть исправлено с помощью неявных преобразований в PostgreSQL или с помощью явных преобразований путем передачи java.sql.Types .ДРУГОЕ для Spring JDBC.
Исключение, которое вы получите
При использовании Spring JDBC или Spring Data JDBC и пользовательских типов Java enum вы можете столкнуться со следующей проблемой:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT * FROM your_table where enum_column = :enum_value;] nested exception is org.postgresql.util.PSQLException: ERROR: operator does not exist: my_enum_type = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Заставить метод сохранения Spring Data JDBC работать с перечислениями
С Spring Data JDBC у вас, вероятно, есть определение SQL, например:
CREATE TYPE my_enum_type AS ENUM(‘VALUE_1′,’VALUE_2’)
CREATE TABLE my_table (enum_column my_enum_type);
Как только вы попытаетесь вызвать repository.save, вы получите исключение. Проблема в том, что Spring Data JDBC на данный момент не поддерживает перечисления. Смотрите Ответ Йенса Шаудера в stackoverflow .
Использование JdbcTemplate и перечислений
Вы можете подумать, что указанное определение CREATE CAST также будет работать для чего-то подобного:
public class MyRepository {
@Autowired
NamedParameterJdbcTemplate jdbcTemplate;
public List<String> findAll() {
MapSqlParameterSource parameters = new MapSqlParameterSource(“type”, MyEnumType.VALUE_1);
return jdbcTemplate
.queryForList(“SELECT enum_column FROM my_table WHERE enum_column = :type”, parameters);
}
}
Но это приведет вас прямо к исключению, которое вы найдете в начале:
org.postgresql.util.PSQLException: ERROR: operator does not exist: my_enum_type = character varying
Причина такого поведения заключается в том, как PostgreSQL обрабатывает приведение типов. В этом ответе Stackoverflow подробно описаны причины. Spring JDBC автоматически преобразует значение enum в строковый тип Java и присваивает его подготовленному оператору. Затем базовые драйверы PgJDBC присваивают java.sql.Type.VARCHAR в качестве типа для этого параметра подготовленного оператора. Из-за назначения java.sql.Type PostgreSQL больше не будет пытаться применить наше преобразование CREATE CAST.
Отладка ошибки “связь не существует” в postgres
Итак, я получал эту неприятную ошибку, даже когда таблица явно существовала в базе данных t11.
Даже после долгих поисков в Google, отладки и попыток решения Stackoverflow разрешения не было. Затем у меня возникло подозрение, что я должен проверить, какая база данных и схема фактически использовались при выполнении программно (хотя dbname было четко указано в строке подключения).
Если вы используете database t11, запустив \c t11, а затем запустите:
выберите * из information_schema.tables, где table_schema ОТСУТСТВУЕТ (‘pg_catalog’, ‘information_schema’)
Он сообщит вам, что userinfo5 существует в базе данных t11. Но что происходит, когда мы пытаемся получить к нему программный доступ?
Итак, я запустил приведенный выше запрос в функции golang, функции, которая ранее выполняла запрос select * из userinfo5, где>
Вывод показал, что имя базы данных, которое фактически использовалось, было postgres, а не t11 Почему?
Потому что мой пользователь postgres был настроен на то, чтобы не использовать пароль. Но в моей строке подключения был пароль = Это как-то сбивало с толку драйвер БД, и использовалась база данных postgres, а не t11.
удалите пароль = из строки подключения, чтобы он выглядел так: “хост = порт локального хоста = 5432 пользователь = postgres dbname= t11 sslmode = отключить”
Измените postgres пользователя, чтобы он использовал пароль: измените postgres пользователя с паролем ‘pwd123’;
Измените строку подключения: “хост = порт локального хоста = 5432 пользователь = пароль postgres = pwd123 dbname = t11 sslmode = отключить”