Dlaczego tak się dzieje
Problem polega na tym, że PostgreSQL zbyt rygorystycznie podchodzi do rzutowania między tekstowymi i nietekstowymi typami danych. Nie pozwoli na niejawne rzutowanie (bez CAST
lub ::
w SQL) z typu tekstowego, takiego jak text
lub varchar
(character varying
) do typu nietekstowego podobnego do tekstu, takiego jak json
, xml
itp.
Sterownik PgJDBC określa typ danych varchar
kiedy wywołasz setString
aby przypisać parametr. Jeśli typ bazy danych kolumny, argumentu funkcji itp. nie jest w rzeczywistości varchar
lub text
, ale zamiast innego typu pojawia się błąd typu. Dotyczy to również wielu innych sterowników i ORM-ów.
PgJDBC:stringtype=unspecified
Najlepszą opcją podczas korzystania z PgJDBC jest ogólnie przekazanie parametru stringtype=unspecified
. Zastępuje to domyślne zachowanie przekazywania setString
wartości jako varchar
i zamiast tego pozostawia bazę danych, aby "odgadła" ich typ danych. W prawie wszystkich przypadkach robi to dokładnie to, czego chcesz, przekazując ciąg do walidatora danych wejściowych dla typu, który chcesz przechowywać.
Wszystko:CREATE CAST ... WITH FUNCTION ...
Możesz zamiast tego CREATE CAST
zdefiniować rzutowanie specyficzne dla typu danych, aby zezwolić na to na podstawie typu po typie, ale może to mieć skutki uboczne w innych miejscach. Jeśli to zrobisz, nie użyj WITHOUT FUNCTION
rzutowania, ominą sprawdzanie poprawności typu i spowodują błędy. Musisz użyć funkcji wejścia/walidacji dla typu danych. Korzystanie z CREATE CAST
jest odpowiedni dla użytkowników innych sterowników baz danych, którzy nie mają możliwości zatrzymania sterownika określającego typ parametrów łańcucha/tekstu.
np.
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;
Wszystko:obsługa typu niestandardowego
Jeśli Twój ORM na to pozwala, możesz zaimplementować niestandardową procedurę obsługi typu dla typu danych i tego konkretnego ORM. Jest to szczególnie przydatne, gdy używasz natywnego typu Java, który dobrze odwzorowuje typ PostgreSQL, zamiast używania String
, ale może również działać, jeśli Twój ORM pozwala określić procedury obsługi typu za pomocą adnotacji itp.
Metody implementacji niestandardowych programów obsługi typów są specyficzne dla sterownika, języka i ORM. Oto przykład dla Javy i Hibernate dla json
.
PgJDBC:wpisz procedurę obsługi za pomocą PGObject
Jeśli używasz natywnego typu Java w Javie, możesz rozszerzyć PGObject
aby zapewnić mapowanie typu PgJDBC dla twojego typu. Prawdopodobnie będziesz musiał również zaimplementować procedurę obsługi typu specyficznego dla ORM, aby użyć swojego PGObject
, ponieważ większość ORM-ów po prostu wywoła toString
na typach, których nie rozpoznają. Jest to preferowany sposób mapowania złożonych typów między Javą i PostgreSQL, ale także najbardziej złożony.
PgJDBC:Procedura obsługi typu za pomocą setObject(int, Object)
Jeśli używasz String
aby przechowywać wartość w Javie, a nie bardziej konkretny typ, możesz wywołać metodę JDBC setObject(integer, Object)
do przechowywania ciągu bez określonego typu danych. Sterownik JDBC wyśle reprezentację ciągu, a baza danych wywnioskuje typ z docelowego typu kolumny lub typu argumentu funkcji.
Zobacz także
Pytania:
- Mapowanie kolumny postgreSQL JSON na typ wartości Hibernate
- Czy możliwe są niestandardowe typy JPA (EclipseLink)?
Zewnętrzne:
- http://www.postgresql.org/identyfikator-wiadomości/[email protected]
- https://github.com/pgjdbc/pgjdbc/issues/265
- http://www.pateldenish.com/2013/05/inserting-json-data-into-postgres-using-jdbc-driver.html