Recentemente ho risolto un compito simile. Immagino sia troppo tardi, ma forse qualcuno lo trova utile.
Risposta breve: è necessario creare una classe (come "com.test.MyJsonType"), che deve implementare org.hibernate.usertype.UserType interfaccia in cui il metodo nullSafeGet dovrebbe deserializzare JSON per oggetto Java (usando Jackson), il nullSafeSet serializza POJO in JSON e alcuni altri metodi ausiliari.
Quindi è necessario estendere MySQLDialect e registrare il nuovo tipo di colonna "json".
Infine è possibile annotare i campi di entità da @type (type = "com.test.MyJsonType"), che dovrebbe essere mappato a MySQL colonne JSON.
Si può anche leggere su @TypeDef here se non si desidera scrivere il tipo con nome del pacchetto.
Ad esempio:
public class MyJsonType implements UserType {
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@Override
public Class<Characteristics> returnedClass() {
return Characteristics.class;
}
@Override
public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, final Object owner)
throws HibernateException, SQLException {
final String cellContent = rs.getString(names[0]);
if (cellContent == null) {
return null;
}
try {
final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue(cellContent.getBytes("UTF-8"), returnedClass());
} catch (final Exception ex) {
throw new RuntimeException("Failed to convert String to Invoice: " + ex.getMessage(), ex);
}
}
@Override
public void nullSafeSet(final PreparedStatement ps, final Object value, final int idx, final SessionImplementor session)
throws HibernateException, SQLException {
if (value == null) {
ps.setNull(idx, Types.VARCHAR);
return;
}
try {
final ObjectMapper mapper = new ObjectMapper();
final StringWriter w = new StringWriter();
mapper.writeValue(w, value);
w.flush();
ps.setObject(idx, w.toString(), Types.VARCHAR);
} catch (final Exception ex) {
throw new RuntimeException("Failed to convert Invoice to String: " + ex.getMessage(), ex);
}
}
@Override
public Object deepCopy(final Object value) throws HibernateException {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(value);
oos.flush();
oos.close();
bos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
return new ObjectInputStream(bais).readObject();
} catch (ClassNotFoundException | IOException ex) {
throw new HibernateException(ex);
}
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(final Object value) throws HibernateException {
return (Serializable) this.deepCopy(value);
}
@Override
public Object assemble(final Serializable cached, final Object owner) throws HibernateException {
return this.deepCopy(cached);
}
@Override
public Object replace(final Object original, final Object target, final Object owner) throws HibernateException {
return this.deepCopy(original);
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return Objects.hashCode(x);
}
}
classe POJO:
public class Characteristics implements Serializable {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field= field;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final Characteristics other = (Characteristics) obj;
return Objects.equals(this.field, other.field);
}
@Override
public int hashCode() {
return Objects.hash(this.field);
}
}
Registrati nuovo tipo di colonna:
public class JsonMySQLDialect extends MySQLDialect {
public JsonMySQLDialect() {
this.registerColumnType(Types.VARCHAR, "json");
}
}
Usando:
@Entity
@Table(name = "Table")
public class TableClass {
...
@Column
@Type(type = "com.test.MyJsonType")
protected Characteristics characteristics;
...
}
Direi che è possibile, ma non penso che ci sia un modo semplice, certamente è un sacco di lavoro ... conosci 'torodb'? Stanno facendo un po 'la stessa cosa, ma immagino che non usano 'HQL' e sotto hanno' postgresql' ... Buona fortuna. – lrnzcig
Grazie per le informazioni! –