2015-09-28 13 views
9

Mam zamiar rozpocząć projekt, w którym muszę generować dynamiczne formularze google. Wymogiem tego projektu jest użycie mysql 5.7, aby móc używać json datatype do przechowywania/pobierania danych json. Czuję się z tym dobrze. Wiem, że jest to możliwe przy użyciu HQL. Ale nie mogłem zrozumieć, w jaki sposób mogę go zaimplementować za pomocą Hibernuj używając mapowania relacyjnego obiektu?Przechowywanie/pobieranie danych Json do/z bazy danych MySQL 5.7 przy użyciu hibernacji

Jakieś pomysły?

Z góry dziękuję!

+0

Zgaduję, że jest to możliwe, jednak nie sądzę, że istnieje prosty sposób, z pewnością jest to dużo pracy ... Czy znasz 'torodb'? Robią coś podobnego, ale myślę, że nie używają "HQL", a pod spodem mają 'postgresql' ... Powodzenia. – lrnzcig

+0

Dzięki za informacje! –

Odpowiedz

3

Niedawno rozwiązałem podobne zadanie. Sądzę, że jest za późno, ale może ktoś uzna to za przydatne.

Krótka odpowiedź: należy utworzyć klasę (jak "com.test.MyJsonType"), które muszą wdrożyć org.hibernate.usertype.UserType interfejs gdzie nullSafeGet metoda powinna deserializować JSON do obiektu java (używając Jackson), nullSafeSet serializuje POJO do JSON i kilka innych metod pomocniczych.

Następnie należy rozszerzyć MySQLDialect i zarejestrować nowy typ kolumny "json".

Wreszcie można dodać pola encji przez @ Type (type = "com.test.MyJsonType"), który powinien zostać zmapowany do kolumn json MySQL.

Możesz również przeczytać o @TypeDef here, jeśli nie chcesz pisać z nazwą pakietu.

Na przykład:

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); 
} 

} 

klasy 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); 

} 
} 

rejestracja nowego typu kolumna

public class JsonMySQLDialect extends MySQLDialect { 

public JsonMySQLDialect() { 
    this.registerColumnType(Types.VARCHAR, "json"); 
} 

} 

Zastosowanie:

@Entity 
@Table(name = "Table") 
public class TableClass { 
... 
@Column 
@Type(type = "com.test.MyJsonType") 
protected Characteristics characteristics; 
... 
} 
+0

Czy tworzy kolumnę typu "json" lub varchar? – gtiwari333

+0

Tworzy kolumnę typu "json". –

+2

Java automatycznie wywołuje super(). Ale jeśli chcesz, możesz to jawnie nazwać. –

Powiązane problemy