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