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:
- https://www.postgresql.org/message-id/example@sqldat.com
- https://github.com/pgjdbc/pgjdbc/issues/265
- https://www.pateldenish.com/2013/05/inserting-json-data-into-postgres-using-jdbc-driver.html