Rad
Rad

Reputation: 4982

How to have implement Hibnernate type for raw JSON + JSON(B) PostgreSQL

Problem: I'm gonna use [Hibernate-Types][1] by @vlad-mihalcea and I need to implement an Hibernate type for raw JSON values in my entity:

public class Entity {
  ...
  @Type(type = "rawjson") // or rawjsonb
  private String json;
}

For (string) 'json' type I've implemented:

public class RawJsonStringType extends ImmutableType<String> {

    public RawJsonStringType() {
        super(String.class);
    }

    @Override
    protected String get(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException {
        return rs.getString(names[0]);
    }

    @Override
    protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException {
        st.setString(index, value);
    }

    @Override
    public int[] sqlTypes() {
        return new int[] { JAVA_OBJECT }; // it creates a 'json' column
    }

}

And for (binary) 'jsonb' type:

public class RawJsonBinaryType extends ImmutableType<String> {

    public RawJsonBinaryType() {
        super(String.class);
    }

    @Override
    protected String get(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException {
        return rs.getString(names[0]);
    }

    @Override
    protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException {
        st.setString(index, value);
    }

    @Override
    public int[] sqlTypes() {
        return new int[] { JAVA_OBJECT - 1 }; // to have a 'jsonb' column, must be registered in the dialect: registerColumnType(Types.JAVA_OBJECT - 1, "json");
    }

}

But when I test it, it fails with the following:

Caused by: org.postgresql.util.PSQLException: ERROR: column "rawjson" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 123

Upvotes: 0

Views: 519

Answers (2)

Rad
Rad

Reputation: 4982

It was almost correct:

@Override
protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException {
    st.setObject(index, value, Types.OTHER);
}

Upvotes: 0

Vlad Mihalcea
Vlad Mihalcea

Reputation: 153730

Just map it as a JsonNode and it will work. So, from String, you need to build the Jackson JsonNode.

If you want to map it as String, you'd have to write a new custom Type. But, why would you do that?

Upvotes: 1

Related Questions