I'm trying to persist java object into jsonb column into Postgres database using eclipselink, but I am stuck at the moment on writing an appropriate converter. Can anyone help me or give me a good example of persisting jsonb types in java with eclipselink?
Here is model code:
@Entity
@Table(name = TABLE_NAME)
public class SystemEventModel implements Serializable {
public static final String TABLE_NAME = "system_event";
@Id
@Column(name = "id")
private Long id;
@Lob
@Column(name = "event_data", columnDefinition = "jsonb")
private JsonObject eventData;
public SystemEventModel(JsonObject eventData) {
this.eventData = eventData;
}
}
Currently, I just get the error "ERROR: column "event_data" is of type jsonb but the expression is of type bytea" when I try to persist this object. I'm aware why it is but I don't know how to write a converter since I don't understand in what type should I convert the JsonObject type for it to get passed like jsonb.
Here is what I mean in this converter sample:
@Converter(autoApply = true)
public class AppAttributeTypeAttributeConverter implements AttributeConverter<JsonObject, ???> {
@Override
public ??? convertToDatabaseColumn(JsonObject eventData) {
return ???;
}
@Override
public JsonObject convertToEntityAttribute(??? eventData) {
return ???;
}
}
And here is snippet for persisting:
String details = "{ \"pressed\": \"yes\", \"isDefault\": \"true\", \"type\": \"BUTTON\"}";
JsonReader jsonReader = Json.createReader(new StringReader(details));
JsonObject jsonObject = jsonReader.readObject();
jsonReader.close();
SystemEventModel eventModel = new SystemEventModel(jsonObject);
em.persist(eventModel);
Thanks in advance!
Here is what you can do that may work:
Change
@Lob
@Column(name = "event_data", columnDefinition = "jsonb")
private JsonObject eventData;
to
@Lob
@Type(type = "jsonb")
@Column(name = "event_data", columnDefinition = "jsonb")
private String eventData;
public SystemEventModel(String eventData) {
this.eventData = eventData;
}
Then persist by using this:
String details = "{ \"pressed\": \"yes\", \"isDefault\": \"true\", \"type\": \"BUTTON\"}";
SystemEventModel eventModal = new SystemEventModel(details); // or you can use setter method.
em.persist(eventModel);
I hope it helps!!
Refer How to map a String JPA property to a JSON column using Hibernate
Thanks...
EDIT:-
@Override
public Object convertToDatabaseColumn(JsonObject eventData) {
try {
PGobject out = new PGobject();
out.setType("json");
out.setValue(eventData.toString());
return out;
} catch (Exception e) {
throw new IllegalArgumentException("Unable to serialize to json field ", e);
}
}
@Override
public JsonObject convertToEntityAttribute(Object eventData) {
try {
if (eventData instanceof PGobject && ((PGobject) eventData).getType().equals("json")) {
return mapper.reader(new TypeReference<JsonObject>() {
}).readValue(((PGobject) eventData).getValue());
}
return Json.createObjectBuilder().build();
} catch (IOException e) {
throw new IllegalArgumentException("Unable to deserialize to json field ", e);
}
}
This is the Solution I found for JPA not specifically for hibernate or eclipselink.