Защо се случва
Проблемът е, че PostgreSQL е прекалено строг по отношение на прехвърлянията между текстови и нетекстови типове данни. Той няма да позволи имплицитно прехвърляне (това без CAST
или ::
в SQL) от текстов тип като text
или varchar
(character varying
) към текстово-подобен нетекстов тип като json
, xml
и др.
Драйверът PgJDBC определя типа данни на varchar
когато извикате setString
за да зададете параметър. Ако типът на базата данни на колоната, аргумента на функцията и т.н. всъщност не е varchar
или text
, но вместо друг тип получавате грешка при типа. Това важи и за доста други драйвери и ORM.
PgJDBC:stringtype=unspecified
Най-добрият вариант при използване на PgJDBC обикновено е да се предаде параметърът stringtype=unspecified
. Това отменя поведението по подразбиране за предаване на setString
стойности като varchar
и вместо това оставя на базата данни да "отгатне" техния тип данни. В почти всички случаи това прави точно това, което искате, като предава низа на валидатора на входа за типа, който искате да съхраните.
Всички:CREATE CAST ... WITH FUNCTION ...
Вместо това можете да CREATE CAST
за да се дефинира специфично за тип данни прехвърляне, за да се позволи това на база тип по тип, но това може да има странични ефекти другаде. Ако направите това, не използвайте WITHOUT FUNCTION
cast, те ще заобиколят валидирането на типа и ще доведат до грешки. Трябва да използвате функцията за въвеждане/проверка за типа данни. Използване на CREATE CAST
е подходящ за потребители на други драйвери на база данни, които нямат начин да спрат драйвера, указващ типа за параметрите на низ/текст.
напр.
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;
Всички:Манипулатор на персонализиран тип
Ако вашият ORM позволява, можете да внедрите персонализиран манипулатор на тип за типа данни и този конкретен ORM. Това най-вече е полезно, когато използвате естествен тип Java, който се съпоставя добре с типа PostgreSQL, вместо да използвате String
, въпреки че може да работи и ако вашият ORM ви позволява да задавате манипулатори на типове, като използвате пояснения и т.н.
Методите за внедряване на манипулатори на персонализирани типове са специфични за драйвера, езика и ORM. Ето пример за Java и Hibernate за json
.
PgJDBC:тип манипулатор, използващ PGObject
Ако използвате роден тип Java в Java, можете да разширите PGObject
за да предоставите съпоставяне на тип PgJDBC за вашия тип. Вероятно ще трябва да внедрите и специфичен за ORM манипулатор на тип, за да използвате вашия PGObject
, тъй като повечето ORM просто ще извикат toString
за видовете, които не разпознават. Това е предпочитаният начин за картографиране на сложни типове между Java и PostgreSQL, но и най-сложният.
PgJDBC:Манипулатор на типа с помощта на setObject(int, Object)
Ако използвате String
за да задържите стойността в Java, а не по-специфичен тип, можете да извикате метода JDBC setObject(integer, Object)
за да съхранявате низа без определен конкретен тип данни. JDBC драйверът ще изпрати низовото представяне и базата данни ще изведе типа от типа на колоната на местоназначението или типа аргумент на функцията.
Вижте също
Въпроси:
- Съпоставяне на колоната на postgreSQL JSON с тип стойност на Hibernate
- Възможни ли са персонализирани типове JPA (EclipseLink)?
Външен:
- 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