How to use Postgres JSONB datatype with JPA?

后端 未结 3 902
一生所求
一生所求 2020-12-01 05:38

Im not finding a way to map the JSON and JSONB datatypes from PostgreSQL using JPA (EclipseLink). Is some one using this datatypes with JPA and can give me some working exam

3条回答
  •  北海茫月
    2020-12-01 06:05

    Edit: I see now that this is pretty much Hibernate dependent. But perhaps you can find something similar for EclipseLink.

    I'll just add what I have as an answer, it originates from another SO answer but whatever. This will map jsonb to JsonObject of Google gson, but you can change it to something else if needed. To change to something else, change nullSafeGet, nullSafeSetand deepCopy methods.

    public class JsonbType implements UserType {
    
        @Override
        public int[] sqlTypes() {
            return new int[] { Types.JAVA_OBJECT };
        }
    
        @Override
        public Class 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);
        }
    }
    

    To use this, do:

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

    In addition, you need to set your dialect to indicate that JAVA_OBJECT = jsonb:

    registerColumnType(Types.JAVA_OBJECT, "jsonb");
    

提交回复
热议问题