sql >> Database teknologi >  >> RDS >> PostgreSQL

Lagring af json, jsonb, hstore, xml, enum, ipaddr osv. mislykkes med kolonne x er af typen json, men udtryk er af typen, der varierer

Hvorfor sker det

Problemet er, at PostgreSQL er alt for streng med hensyn til casts mellem tekst og ikke-tekst datatyper. Det vil ikke tillade en implicit cast (en uden en CAST). eller :: i SQL) fra en teksttype som text eller varchar (character varying ) til en tekstlignende ikke-teksttype som json , xml osv.

PgJDBC-driveren specificerer datatypen varchar når du kalder setString at tildele en parameter. Hvis databasetypen for kolonnen, funktionsargument osv. ikke faktisk er varchar eller text , men i stedet for en anden type, får du en typefejl. Dette gælder også for en hel del andre drivere og ORM'er.

PgJDBC:stringtype=unspecified

Den bedste mulighed ved brug af PgJDBC er generelt at videregive parameteren stringtype=unspecified . Dette tilsidesætter standardadfærden ved at sende setString værdier som varchar og i stedet overlader det til databasen at "gætte" deres datatype. I næsten alle tilfælde gør dette præcis, hvad du ønsker, og sender strengen til inputvalidatoren for den type, du vil gemme.

Alle:CREATE CAST ... WITH FUNCTION ...

Du kan i stedet CREATE CAST at definere en datatype-specifik cast for at tillade dette på en type-for-type basis, men dette kan have bivirkninger andre steder. Hvis du gør dette, skal du ikke brug WITHOUT FUNCTION casts, vil de omgå typevalidering og resultere i fejl. Du skal bruge input/valideringsfunktionen for datatypen. Brug CREATE CAST er velegnet til brugere af andre databasedrivere, der ikke har nogen måde at stoppe driveren ved at angive typen for streng/tekst-parametre.

f.eks.

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;

Alle:Custom type handler

Hvis din ORM tillader det, kan du implementere en brugerdefineret typebehandler for datatypen og den specifikke ORM. Dette er mest nyttigt, når du bruger indbygget Java-type, der passer godt til PostgreSQL-typen, i stedet for at bruge String , selvom det også kan fungere, hvis din ORM lader dig specificere typebehandlere ved hjælp af annoteringer osv.

Metoder til implementering af brugerdefinerede typebehandlere er driver-, sprog- og ORM-specifikke. Her er et eksempel for Java og Hibernate for json .

PgJDBC:typebehandler ved hjælp af PGObject

Hvis du bruger en indbygget Java-type i Java, kan du udvide PGObject for at give en PgJDBC type mapping for din type. Du skal sandsynligvis også implementere en ORM-specifik typebehandler for at bruge dit PGObject , da de fleste ORM'er bare kalder toString på typer, de ikke genkender. Dette er den foretrukne måde at kortlægge komplekse typer mellem Java og PostgreSQL, men også den mest komplekse.

PgJDBC:Typebehandler ved hjælp af setObject(int, Object)

Hvis du bruger String for at holde værdien i Java i stedet for en mere specifik type, kan du påberåbe JDBC-metoden setObject(integer, Object) for at gemme strengen uden en bestemt datatype. JDBC-driveren sender strengrepræsentationen, og databasen vil udlede typen fra destinationskolonnetypen eller funktionsargumenttypen.

Se også

Spørgsmål:

  • Kortlægning af postgreSQL JSON-kolonne til Hibernate-værditype
  • Er JPA (EclipseLink) tilpassede typer mulige?

Eksternt:

  • 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



  1. SQLite-undtagelse under forsøg på at slette række

  2. SQLite VAKUUM

  3. Introduktion til PL/SQL-pakker i Oracle-databasen

  4. Bruger AT TIME ZONE til at rette en gammel rapport