Nie znajduję sposobu mapowania typów danych JSON i JSONB z PostgreSQL przy użyciu JPA (EclipseLink). Czy ktoś używa tych danych z JPA i może dać mi jakieś działające przykłady?Jak używać Postgres JSONB typu danych z JPA?
Odpowiedz
Wszystkie odpowiedzi pomogły mi dotrzeć do ostatecznego rozwiązania, które jest gotowe do JPA, a nie EclipseLink lub Hibernate specjalnie.
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import javax.json.Json;
import javax.json.JsonObject;
import javax.persistence.Converter;
import org.postgresql.util.PGobject;
@Converter(autoApply = true)
public class JsonConverter implements javax.persistence.AttributeConverter<JsonObject, Object> {
private static final long serialVersionUID = 1L;
private static ObjectMapper mapper = new ObjectMapper();
@Override
public Object convertToDatabaseColumn(JsonObject objectValue) {
try {
PGobject out = new PGobject();
out.setType("json");
out.setValue(objectValue.toString());
return out;
} catch (Exception e) {
throw new IllegalArgumentException("Unable to serialize to json field ", e);
}
}
@Override
public JsonObject convertToEntityAttribute(Object dataValue) {
try {
if (dataValue instanceof PGobject && ((PGobject) dataValue).getType().equals("json")) {
return mapper.reader(new TypeReference<JsonObject>() {
}).readValue(((PGobject) dataValue).getValue());
}
return Json.createObjectBuilder().build();
} catch (IOException e) {
throw new IllegalArgumentException("Unable to deserialize to json field ", e);
}
}
}
Próbowałem coś takiego dla Hibernuj, ale wydaje się, że "AttributeConverter", który kończy się na 'Object' jest zepsuty przez' Hibernate'. Właśnie pojawia się komunikat "nieznany typ jdbc" lub coś podobnego. Naprawdę szkoda, ponieważ to podejście jest znacznie ładniejsze, z mniejszą ilością blachy kotła. – Tobb
Nie potrzebowałem tego wczoraj, kiedy zadano pytanie, potrzebuję go dzisiaj i wypróbowałem twoje rozwiązanie, tylko po to, aby odkryć, że sterownik JDBC Postgres chce go za pomocą specjalnej metody 'setPGobject', która może być wywołana tylko ręcznie lub jeśli użyj 'setObject', musisz określić typ' java.sql.Types.OTHER', którego nie mogę zrobić. Zmodyfikowalem sterownik, aby wyslal go tam, jesli nieznana i odpowiednia klasa, tylko aby wystapic w konfliktach ClassLoader. Jeśli załaduję sterownik w aplikacji webowej, podczas ładowania ładuję się, ale nie ustawiam. Jeśli załaduję go w katalogu 'tomcat/lib', pojawia się konflikt podczas ustawiania. – coladict
@coladict Opublikowana przeze mnie klasa nie działa dla ciebie? Nie rozumiem twojego problemu bardzo dobrze. Jeśli zobaczysz metodę convertToDatabaseColumn, zwróci obiekt, ale ten obiekt jest już typu PGobject niezbędny dla PostgreS, nie sądzę, że potrzebujesz czegoś więcej. –
Edycja: Teraz widzę, że zależy to w znacznym stopniu od Hibernate
. Ale może można znaleźć coś podobnego dla EclipseLink
..
dodam tylko to, co mam, jako odpowiedź, że wywodzi się od siebie tak odpowiedzieć, ale cokolwiek .. To będzie mapować jsonb
do JsonObject
Google gson
, ale można w razie potrzeby zmień go na coś innego. Aby zmienić na coś innego, zmień metody nullSafeGet
, nullSafeSet
i i .
public class JsonbType implements UserType {
@Override
public int[] sqlTypes() {
return new int[] { Types.JAVA_OBJECT };
}
@Override
public Class<JsonObject> returnedClass() {
return JsonObject.class;
}
@Override
public boolean equals(final Object x, final Object y) {
if (x == y) {
return true;
}
if (x == null || y == null) {
return false;
}
return x.equals(y);
}
@Override
public int hashCode(final Object x) {
if (x == null) {
return 0;
}
return x.hashCode();
}
@Nullable
@Override
public Object nullSafeGet(final ResultSet rs,
final String[] names,
final SessionImplementor session,
final Object owner) throws SQLException {
final String json = rs.getString(names[0]);
if (json == null) {
return null;
}
final JsonParser jsonParser = new JsonParser();
return jsonParser.parse(json).getAsJsonObject();
}
@Override
public void nullSafeSet(final PreparedStatement st,
final Object value,
final int index,
final SessionImplementor session) throws SQLException {
if (value == null) {
st.setNull(index, Types.OTHER);
return;
}
st.setObject(index, value.toString(), Types.OTHER);
}
@Nullable
@Override
public Object deepCopy(@Nullable final Object value) {
if (value == null) {
return null;
}
final JsonParser jsonParser = new JsonParser();
return jsonParser.parse(value.toString()).getAsJsonObject();
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(final Object value) {
final Object deepCopy = deepCopy(value);
if (!(deepCopy instanceof Serializable)) {
throw new SerializationException(
String.format("deepCopy of %s is not serializable", value), null);
}
return (Serializable) deepCopy;
}
@Nullable
@Override
public Object assemble(final Serializable cached, final Object owner) {
return deepCopy(cached);
}
@Nullable
@Override
public Object replace(final Object original, final Object target, final Object owner) {
return deepCopy(original);
}
}
Aby to wykorzystać, zrobić:
public class SomeEntity {
@Column(name = "jsonobject")
@Type(type = "com.myapp.JsonbType")
private JsonObject jsonObject;
Ponadto musisz ustawić swój dialekt, aby wskazać, że JAVA_OBJECT
= jsonb
:
registerColumnType(Types.JAVA_OBJECT, "jsonb");
Dzięki @tobb kodzie zamieszczonych pomógł mi znaleźć rozwiązanie dla mojego przypadku. –
Chyba znalazłem analogię do Hibernate's UserType dla EclipseLink.
http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/annotations_ref.htm#CHDEHJEB
Trzeba dokonać klasy, która implementuje org.eclipse.persistence.mappings.converters.Converter
i robi to za ciebie, a następnie użyć @Convert
adnotacji na każdym polu, gdzie używasz tego typu.
- 1. jak używać typu danych geometrii do tabeli postgres?
- 2. Jak pracować z formularzami szyn i jsonb postgres
- 3. Jak używać Postgres' typ wyliczany z Ecto
- 4. Jak używać niestandardowego typu w kolumnie JPA?
- 5. Jak używać enum w bazie danych Postgres w Rails 3?
- 6. Jak używać czasu joda z JPA (eclipselink)?
- 7. Jak używać node-postgres na serwerze?
- 8. Jak usunąć bazę danych postgres z heroku
- 9. Wybieranie danych do tablicy Postgres
- 10. Jak używać StatelessSession z wiosennymi danymi JPA i Hibernate?
- 11. Jak używać pamięci podręcznej drugiego poziomu Hibernate z JPA?
- 12. Postgres typ danych obsada
- 13. JSONb daty: rzeczywiste daty wewnętrznie?
- 14. Jak uaktualnić bazę danych postgres z 9.3 na 9.4 na heroku?
- 15. Jak wykonać wyszukiwanie uwzględniające wielkość liter w kolumnie Postgres 9.4 JSONB?
- 16. Jak indeksować wartości całkowite jsonb
- 17. jpa mapowanie typu java na typ bazy danych
- 18. Jak używać interfejsu API JPA w JOIN
- 19. Jak używać JPA Enum w klauzuli WH?
- 20. Jak używać zmiennej jako typu
- 21. JPA CriteriaBuilder - Jak używać operatora porównania "IN"
- 22. Jak używać typu wywołania z EventBus
- 23. Jak używać adnotacji typu zamknięcia z Aptaną?
- 24. Korzystanie sails.js z bazy danych istniejące postgres
- 25. Jak używać zmiennej typu rekord w plpgsql?
- 26. Jak używać substr (...) dla kolumn typu danych BIT (...)?
- 27. JPA Hibernate Call Postgres Funkcja Void Return MappingException:
- 28. Kiedy należy używać JCR i kiedy należy używać JPA/RDBMS?
- 29. Jak używać Wzorca Builder dla podmiotów z JPA
- 30. Uzyskiwanie kodowania bazy danych Postgres
Jest to przykład gdzieś na SO, pozwól mi zobaczyć, czy mogę znaleźć ... – Tobb