Come ho spiegato nel this article, l'APP AttributeConverter
è troppo limitata per mappare tipi di oggetti JSON, soprattutto se si desidera salvare loro come JSON binario.
Non è necessario creare tutti questi tipi manualmente, è possibile ottenere semplicemente loro via Maven centrale utilizzando la seguente dipendenza:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Per ulteriori informazioni, visitate il hibernate-types open-source project.
Ora, per spiegare come funziona.
Ho scritto an article su come mappare oggetti JSON sia su PostgreSQL che su MySQL.
per PostgreSQL, è necessario inviare l'oggetto JSON in forma binaria:
public class JsonBinaryType
extends AbstractSingleColumnStandardBasicType<Object>
implements DynamicParameterizedType {
public JsonBinaryType() {
super(
JsonBinarySqlTypeDescriptor.INSTANCE,
new JsonTypeDescriptor()
);
}
public String getName() {
return "jsonb";
}
@Override
public void setParameterValues(Properties parameters) {
((JsonTypeDescriptor) getJavaTypeDescriptor())
.setParameterValues(parameters);
}
}
Il JsonBinarySqlTypeDescriptor
assomiglia a questo:
public class JsonBinarySqlTypeDescriptor
extends AbstractJsonSqlTypeDescriptor {
public static final JsonBinarySqlTypeDescriptor INSTANCE =
new JsonBinarySqlTypeDescriptor();
@Override
public <X> ValueBinder<X> getBinder(
final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>(javaTypeDescriptor, this) {
@Override
protected void doBind(
PreparedStatement st,
X value,
int index,
WrapperOptions options) throws SQLException {
st.setObject(index,
javaTypeDescriptor.unwrap(
value, JsonNode.class, options), getSqlType()
);
}
@Override
protected void doBind(
CallableStatement st,
X value,
String name,
WrapperOptions options)
throws SQLException {
st.setObject(name,
javaTypeDescriptor.unwrap(
value, JsonNode.class, options), getSqlType()
);
}
};
}
}
e JsonTypeDescriptor
in questo modo:
public class JsonTypeDescriptor
extends AbstractTypeDescriptor<Object>
implements DynamicParameterizedType {
private Class<?> jsonObjectClass;
@Override
public void setParameterValues(Properties parameters) {
jsonObjectClass = ((ParameterType) parameters.get(PARAMETER_TYPE))
.getReturnedClass();
}
public JsonTypeDescriptor() {
super(Object.class, new MutableMutabilityPlan<Object>() {
@Override
protected Object deepCopyNotNull(Object value) {
return JacksonUtil.clone(value);
}
});
}
@Override
public boolean areEqual(Object one, Object another) {
if (one == another) {
return true;
}
if (one == null || another == null) {
return false;
}
return JacksonUtil.toJsonNode(JacksonUtil.toString(one)).equals(
JacksonUtil.toJsonNode(JacksonUtil.toString(another)));
}
@Override
public String toString(Object value) {
return JacksonUtil.toString(value);
}
@Override
public Object fromString(String string) {
return JacksonUtil.fromString(string, jsonObjectClass);
}
@SuppressWarnings({ "unchecked" })
@Override
public <X> X unwrap(Object value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isAssignableFrom(type)) {
return (X) toString(value);
}
if (Object.class.isAssignableFrom(type)) {
return (X) JacksonUtil.toJsonNode(toString(value));
}
throw unknownUnwrap(type);
}
@Override
public <X> Object wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
return fromString(value.toString());
}
}
Ora, è necessario dichiarare il nuovo tipo su entrambe le classe vel o in un package-info.java pacchetto di livello descriptior:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
E la mappatura entità sarà simile a questa:
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Location location;
Se stai usando Hibernate 5 o versione successiva, quindi il tipo JSON
è registered automatically by Postgre92Dialect.
In caso contrario, è necessario registrarsi da soli:
public class PostgreSQLDialect extends PostgreSQL91Dialect {
public PostgreSQL92Dialect() {
super();
this.registerColumnType(Types.JAVA_OBJECT, "json");
}
}
Se si dispone di molti parametri di configurazione, basta usare semplice tavolo con 2 colonne: chiave e il valore e caricarlo per mappare. Se vuoi memorizzare parametri come JSON o XML, basta archiviarli/leggerli come testo e convertirli in seguito. – user1516873
@Rad fa [this] (http://stackoverflow.com/questions/22637733/mysql-error-code-1118-row-size-too-large-8126-changing-some-columns-to-te) ti aiuta –
@ user1516873 abbiamo considerato questa come la soluzione finale. Se non sbaglio, aumenta la complessità mentre si tenta di modificare i dati. Grazie comunque. – Rad