Pourquoi cela se produit
Le problème est que PostgreSQL est trop strict sur les transtypages entre les types de données textuels et non textuels. Il n'autorisera pas un cast implicite (un sans CAST
ou ::
dans le SQL) à partir d'un type de texte comme text
ou varchar
(character varying
) à un type non textuel de type texte comme json
, xml
, etc.
Le pilote PgJDBC spécifie le type de données de varchar
lorsque vous appelez setString
pour assigner un paramètre. Si le type de base de données de la colonne, de l'argument de la fonction, etc., n'est pas réellement varchar
ou text
, mais à la place d'un autre type, vous obtenez une erreur de type. Cela est également vrai pour de nombreux autres pilotes et ORM.
PgJDBC :stringtype=unspecified
La meilleure option lors de l'utilisation de PgJDBC est généralement de passer le paramètre stringtype=unspecified
. Cela remplace le comportement par défaut de passer setString
valeurs sous forme de varchar
et laisse à la place à la base de données le soin de "deviner" leur type de données. Dans presque tous les cas, cela fait exactement ce que vous voulez, en passant la chaîne au validateur d'entrée pour le type que vous souhaitez stocker.
Tous :CREATE CAST ... WITH FUNCTION ...
Vous pouvez à la place CREATE CAST
pour définir un cast spécifique au type de données pour permettre cela sur une base type par type, mais cela peut avoir des effets secondaires ailleurs. Si vous faites cela, ne le faites pas utiliser WITHOUT FUNCTION
casts, ils contourneront la validation de type et entraîneront des erreurs. Vous devez utiliser la fonction d'entrée/validation pour le type de données. Utilisation de CREATE CAST
convient aux utilisateurs d'autres pilotes de base de données qui n'ont aucun moyen d'arrêter le pilote en spécifiant le type des paramètres de chaîne/texte.
ex.
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;
Tous :gestionnaire de type personnalisé
Si votre ORM le permet, vous pouvez implémenter un gestionnaire de type personnalisé pour le type de données et cet ORM spécifique. Ceci est particulièrement utile lorsque vous utilisez un type Java natif qui correspond bien au type PostgreSQL, plutôt que d'utiliser String
, bien que cela puisse également fonctionner si votre ORM vous permet de spécifier des gestionnaires de type à l'aide d'annotations, etc.
Les méthodes d'implémentation des gestionnaires de types personnalisés sont spécifiques au pilote, au langage et à l'ORM. Voici un exemple pour Java et Hibernate pour json
.
PgJDBC :gestionnaire de type utilisant PGObject
Si vous utilisez un type Java natif en Java, vous pouvez étendre PGObject
pour fournir un mappage de type PgJDBC pour votre type. Vous devrez probablement également implémenter un gestionnaire de type spécifique à ORM pour utiliser votre PGObject
, puisque la plupart des ORM appelleront simplement toString
sur des types qu'ils ne reconnaissent pas. C'est la méthode préférée pour mapper des types complexes entre Java et PostgreSQL, mais aussi la plus complexe.
PgJDBC :gestionnaire de type utilisant setObject(int, Object)
Si vous utilisez String
pour conserver la valeur en Java, plutôt qu'un type plus spécifique, vous pouvez invoquer la méthode JDBC setObject(integer, Object)
pour stocker la chaîne sans type de données particulier spécifié. Le pilote JDBC enverra la représentation sous forme de chaîne et la base de données déduira le type à partir du type de colonne de destination ou du type d'argument de fonction.
Voir aussi
Question :
- Mappage de la colonne JSON postgreSQL sur le type de valeur Hibernate
- Les types personnalisés JPA (EclipseLink) sont-ils possibles ?
Externe :
- 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