Por que isso acontece
O problema é que o PostgreSQL é muito rígido com relação a conversões entre tipos de dados de texto e não-texto. Não permitirá uma conversão implícita (uma sem um
CAST
ou ::
no SQL) de um tipo de texto como text
ou varchar
(character varying
) para um tipo não-texto semelhante a texto como json
, xml
, etc O driver PgJDBC especifica o tipo de dados de
varchar
quando você chama setString
para atribuir um parâmetro. Se o tipo de banco de dados da coluna, argumento da função, etc, não for realmente varchar
ou text
, mas em vez de outro tipo, você obtém um erro de tipo. Isso também é verdade para muitos outros drivers e ORMs. PgJDBC:stringtype=unspecified
A melhor opção ao usar o PgJDBC é geralmente passar o parâmetro
stringtype=unspecified
. Isso substitui o comportamento padrão de passar setString
valores como varchar
e, em vez disso, deixa para o banco de dados "adivinhar" seu tipo de dados. Em quase todos os casos, isso faz exatamente o que você deseja, passando a string para o validador de entrada do tipo que deseja armazenar. Todos:CREATE CAST ... WITH FUNCTION ...
Em vez disso, você pode
CREATE CAST
para definir uma conversão específica de tipo de dados para permitir isso tipo por tipo, mas isso pode ter efeitos colaterais em outros lugares. Se você fizer isso, não use WITHOUT FUNCTION
casts, eles ignorarão a validação de tipo e resultarão em erros. Você deve usar a função de entrada/validação para o tipo de dados. Usando CREATE CAST
é adequado para usuários de outros drivers de banco de dados que não têm como parar o driver especificando o tipo de parâmetros de string/texto. por exemplo.
CREATE OR REPLACE FUNCTION json_intext(text) RETURNS json AS $$
SELECT json_in($1::cstring);
$$ LANGUAGE SQL IMMUTABLE;
CREATE CAST (text AS json)
WITH FUNCTION json_intext(text) AS IMPLICIT;
Todos:manipulador de tipo personalizado
Se o seu ORM permitir, você poderá implementar um manipulador de tipo personalizado para o tipo de dados e esse ORM específico. Isso é útil principalmente quando você está usando o tipo Java nativo que mapeia bem para o tipo PostgreSQL, em vez de usar
String
, embora também possa funcionar se seu ORM permitir que você especifique manipuladores de tipo usando anotações etc. Os métodos para implementar manipuladores de tipo personalizados são específicos de driver, idioma e ORM. Aqui está um exemplo para Java e Hibernate para
json
. PgJDBC:manipulador de tipos usando PGObject
Se você estiver usando um tipo de Java nativo em Java, poderá estender
PGObject
para fornecer um mapeamento de tipo PgJDBC para seu tipo. Você provavelmente também precisará implementar um manipulador de tipo específico de ORM para usar seu PGObject
, já que a maioria dos ORMs apenas chamará toString
em tipos que eles não reconhecem. Essa é a maneira preferida de mapear tipos complexos entre Java e PostgreSQL, mas também a mais complexa. PgJDBC:manipulador de tipos usando setObject(int, Object)
Se você estiver usando
String
para manter o valor em Java, em vez de um tipo mais específico, você pode invocar o método JDBC setObject(integer, Object)
para armazenar a string sem nenhum tipo de dados específico especificado. O driver JDBC enviará a representação de string e o banco de dados inferirá o tipo do tipo de coluna de destino ou do tipo de argumento da função. Veja também
Questões:
- Mapeando a coluna JSON do postgreSQL para o tipo de valor do Hibernate
- Os tipos personalizados JPA (EclipseLink) são possíveis?
Externo:
- http://www.postgresql.org/message-id/[email protected]
- https://github.com/pgjdbc/pgjdbc/issues/265
- http://www.pateldenish.com/2013/05/inserting-json-data-into-postgres-using-jdbc-driver.html