Wie ich in this article erklärt habe, ist es sehr einfach, JSON-Objekt mit Hibernate persistent zu halten.
Sie müssen all diese Typen nicht manuell erstellen, geben Sie einfach sie über Maven Zentrale mit der folgenden Abhängigkeit erhalten können:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Für weitere Informationen, besuchen Sie die hibernate-types open-source project.
Ich schrieb an article darüber, wie Sie JSON-Objekte auf PostgreSQL und MySQL zuordnen können.
Für PostgreSQL, müssen Sie die JSON-Objekt in eine binäre Form senden:
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);
}
}
Die JsonBinarySqlTypeDescriptor
sieht wie folgt aus:
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()
);
}
};
}
}
und die JsonTypeDescriptor
wie folgt aus:
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());
}
}
Jetzt müssen Sie den neuen Typ für jede Klasse le deklarieren vel oder in einer package-info.java Paketebene descriptior:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
Und die Entitätszuordnung wird wie folgt aussehen:
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Location location;
Das ist es!
Wenn ich hinzufügen '@ JsonIgnore' Annotation, aber ich brauche immer noch von beiden differents Objekte, kann ich zwei Parameter von meiner HTTP-Anfrage bekommen? (wie eine Methode dieser Art: 'public void createPeople (@RequestBody AnEntity entityOne, AnOtherEntity entityTwo) {...}') – Fractaliste
Soweit ich weiß, können Sie den Anfragetext nur einem Objekt zuordnen. Ich bin mir also nicht sicher, ob das möglich ist. Beachten Sie jedoch, dass Sie '@ JsonIgnore' bei Bedarf entweder für die Serialisierung/Deserialisierung verwenden können, indem Sie sie auf Getter/Setter setzen. Ich glaube auch immer noch, dass das Erstellen eines Objekts und seiner Beziehung in einer Anfrage nicht so RESTful ist. Ich würde einen anderen REST-Endpunkt zum Speichern der Objektbeziehung erstellen und verwenden. – oceansize