2016-10-03 2 views

Antwort

10

Alle Antworten haben mir geholfen, die endgültige Lösung zu erreichen, die für JPA und nicht Eclipselink bereit ist, oder speziell Ruhezustand.

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); 
    } 
    } 
} 
+3

Ich habe so etwas für Hibernate versucht, aber es scheint 'AttributeConverter', der mit' Object' endet, mit 'Hibernate' zu ​​brechen. Ich bekomme nur einen Fehler, der "unbekannter jdbc-Typ" oder so ähnlich sagt. Schade wirklich, da dieser Ansatz viel schöner ist, mit weniger Kesselplatte. – Tobb

+0

Ich habe diese gestern nicht brauchen, wenn die Frage gestellt wurde, habe ich es heute brauchen und Ihre Lösung versucht, nur um zu entdecken, dass der Postgres JDBC-Treiber es durch eine spezielle Methode will 'setPGobject', die nur manuell, wenn Sie angerufen werden können oder benutze 'setObject', du musst den Typ zu' java.sql.Types.OTHER' angeben, was ich nicht kann. Ich änderte den Treiber, um es dort zu senden, wenn unbekannt und die richtige Klasse, nur um in ClassLoader-Konflikten zu laufen. Wenn ich den Treiber in der Webapp lade bekomme ich einen Konflikt beim Laden, aber nicht einstellen. Wenn ich es im 'tomcat/lib'-Verzeichnis lade, bekomme ich den Konflikt beim Setzen. – coladict

+0

@coladict Die Klasse, die ich gepostet habe, funktioniert nicht für dich? Ich verstehe dein Problem nicht sehr gut. Wenn Sie die Methode convertToDatabaseColumn sehen, gibt es ein Objekt zurück, aber dieses Objekt ist bereits vom Typ PGobject, das für Postgres notwendig ist. Ich glaube nicht, dass Sie mehr brauchen. –

4

Edit: Ich sehe jetzt, dass dies ziemlich Hibernate abhängig ist. Aber vielleicht können Sie etwas ähnliches für EclipseLink finden ..

Ich werde nur hinzufügen, was ich als Antwort, es von einem anderen stammt SO beantworten, aber was auch immer .. Diese jsonb-JsonObject von Google-Karte wird gson, aber Sie können ändere es bei Bedarf in etwas anderes. Um zu etwas anderem zu wechseln, ändern Sie die Methoden nullSafeGet, nullSafeSet und deepCopy.

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); 
    } 
} 

Um dies zu nutzen, tun:

public class SomeEntity { 

    @Column(name = "jsonobject") 
    @Type(type = "com.myapp.JsonbType") 
    private JsonObject jsonObject; 

Darüber hinaus können Sie Ihren Dialekt festlegen müssen, um anzuzeigen, dass JAVA_OBJECT = jsonb:

registerColumnType(Types.JAVA_OBJECT, "jsonb"); 
+0

Dank @tobb den Code finden Sie mich auf dem Laufenden geholfen, eine Lösung für meinen Fall zu finden. –

Verwandte Themen