2015-09-28 14 views
9

Avvierò un progetto in cui è necessario generare moduli google dinamici. Il requisito per questo progetto è che ho bisogno di usare mysql 5.7 in modo da poter usare il tipo di dati json per archiviare/recuperare i dati JSON. Sto bene con questo. Lo so, è possibile usare HQL. Ma quello che non riuscivo a capire è come implementarlo con Hibernate usando la mappatura relazionale degli oggetti?Memorizza/recupera i dati Json da/verso il database Mysql 5.7 utilizzando la sospensione

Qualsiasi idea?

Grazie in anticipo!

+0

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

+0

Grazie per le informazioni! –

risposta

3

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; 
... 
} 
+0

Crea una colonna di tipo "json" o varchar? – gtiwari333

+0

Crea un tipo di colonna "json". –

+2

Java chiama automaticamente super(). Ma se vuoi, puoi chiamarlo esplicitamente. –

Problemi correlati