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
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
, nullSafeSet
and 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");