2016-10-03 2 views

답변

10

모든 답변을 통해 JPA에 대한 준비가되어 있고 EclipseLink 또는 Hibernate가 아닌 최종 솔루션에 도달 할 수있었습니다. 어딘가 SO에 대한 예제가있다

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

나는 Hibernate에서 이와 같은 것을 시도했지만,'Object'로 끝나는'AttributeConverter'는'Hibernate'로 깨졌습니다. 나는 "unknown jdbc type"또는 이와 비슷한 것을 말하는 에러를 얻는다. 부끄러운 줄 아는 사실은이 방법이 보일러 접시가 적어 훨씬 더 예쁘기 때문입니다. – Tobb

+0

어제 질문이 있었을 때이 질문이 필요하지 않았다. 나는 오늘 그것을 필요로하고 해결책을 시도했다. 단지 Postgres JDBC 드라이버가 수동으로 호출 할 수있는 특별한 메소드'setPGobject'를 원한다는 것을 발견했다. 'setObject'를 사용하면 java.sql.Types.OTHER'에 타입을 지정해야합니다. 할 수 없습니다. 알 수 없거나 올바른 클래스 인 경우 드라이버를 수정하여 ClassLoader 충돌 만 실행하도록 수정했습니다. webapp에서 드라이버를로드하면로드 할 때 충돌이 발생하지만 설정은되지 않습니다. 'tomcat/lib' 디렉토리에로드하면 설정시 충돌이 발생합니다. – coladict

+0

@coladict 내가 게시 한 수업이 당신을 위해 일하지 않고 있습니까? 나는 당신의 문제를 잘 이해하지 못한다. convertToDatabaseColumn 메서드를 보면 객체를 반환하지만이 객체는 이미 Postgres에 필요한 PGobject 유형입니다. 그 이상의 것을 필요로하지는 않습니다. –

4

편집 : 이제 꽤 많이 보입니다. Hibernate. 그러나 아마 당신은 그렇게 대답하지만, 무엇이든 ..이 구글 gsonJsonObjectjsonb 매핑합니다 서로 유래, 난 그냥 대답으로 내가 무엇을 추가 할 것입니다

EclipseLink에 대한 비슷한 .. 찾을 수 있습니다,하지만 당신은 할 수 필요한 경우 다른 것으로 변경하십시오. 다른 것으로 변경하려면 nullSafeGet, nullSafeSetdeepCopy 메소드를 변경하십시오. 이를 사용하려면

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

는 수행

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

감사를 보자 내 경우에 대한 해결책을 찾기 위해 저를 도왔다. –

2

이 난에 비유를 찾은 것 같아 :

public class SomeEntity { 

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

는 또한, 당신은 jsonb = JAVA_OBJECT을 나타 내기 위해 당신의 방언을 설정해야 EclipseLink를위한 Hibernate의 UserType.

http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/annotations_ref.htm#CHDEHJEB

당신은 당신이 그 유형을 사용하는 경우 다음 각 필드에 @Convert 주석을 사용, org.eclipse.persistence.mappings.converters.Converter를 구현하고 당신을위한 변환을 수행하는 클래스를 확인해야합니다.

관련 문제