将 JsonNode 对象映射到 SQL DB JPA 中的字符串字段
Map a JsonNode object to a String field in SQL DB JPA
我得到了一个 Sql table,其中包含这些字段:
id uniqueidentifier primary key,
<--Omitting extra fields -->
metadata nvarchar(max)
我还有一个实体映射到它:
@Data
public class GenericEntity implements Serializable {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Type(type = "uuid-char")
private UUID id;
<--Omitting extra properties -->
@Type(type = "string")
private JsonNode metadata;
}
作为 JsonNode 的第二个字段需要能够接受不同类型的 json 并将其作为字符串存储在 table 中。
如何转换 JsonNode 字段并将其作为字符串存储在数据库中,然后当我从 table 中读取时它会将字符串转换回 JsonNode?
有效负载:
{
"id": "db8e8d4b-eee2-4507-bf30-f55c3f948724",
<-- Omitting extra properties -->
"metadata": {
"description": "Sample",
"location": "Stack Overflow"
}
}
现在每次我尝试保存它时都会收到错误消息:
Could not determine type for: com.fasterxml.jackson.databind.JsonNode, at table: table_name, for columns: [org.hibernate.mapping.Column(metadata)]
我遵循了这些说明:
https://www.baeldung.com/hibernate-custom-types
创建了一个 SqlTypeDescriptor
public class JsonNodeStringType extends AbstractSingleColumnStandardBasicType<JsonNode> implements DiscriminatorType<JsonNode> {
public static final JsonNodeStringType INSTANCE = new JsonNodeStringType();
public JsonNodeStringType() {
super(VarcharTypeDescriptor.INSTANCE, JsonNodeStringJavaDescriptor.INSTANCE);
}
@Override
public String getName() {
return "jsonnode";
}
@Override
public JsonNode stringToObject(String xml) {
return fromString(xml);
}
@Override
public String objectToSQLString(JsonNode value, Dialect dialect) {
return '\'' + toString(value) + '\'';
}
}
然后我创建了一个 Java 类型描述符:
public class JsonNodeStringJavaDescriptor extends AbstractTypeDescriptor<JsonNode> {
public static final ObjectMapper mapper = new ObjectMapper();
public static final JsonNodeStringJavaDescriptor INSTANCE = new JsonNodeStringJavaDescriptor();
public JsonNodeStringJavaDescriptor() {
super(JsonNode.class, ImmutableMutabilityPlan.INSTANCE);
}
@Override
public String toString(JsonNode value) {
try {
return mapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("The given JsonNode object value: " + value + " cannot be transformed to a String", e);
}
}
@Override
public JsonNode fromString(String string) {
try {
return mapper.readTree(string);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("The given string value: " + string + " cannot be transformed to JsonNode object", e);
}
}
@Override
public <X> X unwrap(JsonNode value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isAssignableFrom(type)) {
return (X) toString(value);
}
throw unknownUnwrap(type);
}
@Override
public <X> JsonNode wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isInstance(value)) {
return fromString(value.toString());
}
throw unknownWrap(value.getClass());
}
然后将类型定义添加到实体模型
@Data
@TypeDef(name = "jsonnode", typeClass = JsonNodeStringType.class)
public class GenericEntity implements Serializable {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Type(type = "uuid-char")
private UUID id;
<--Omitting extra properties -->
@Type(type = "jsonnode")
private JsonNode metadata;
}
如果你不想手动创建这些类型描述符你也可以按照这篇文章使用外部依赖:https://vladmihalcea.com/sql-server-json-hibernate/
我得到了一个 Sql table,其中包含这些字段:
id uniqueidentifier primary key,
<--Omitting extra fields -->
metadata nvarchar(max)
我还有一个实体映射到它:
@Data
public class GenericEntity implements Serializable {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Type(type = "uuid-char")
private UUID id;
<--Omitting extra properties -->
@Type(type = "string")
private JsonNode metadata;
}
作为 JsonNode 的第二个字段需要能够接受不同类型的 json 并将其作为字符串存储在 table 中。
如何转换 JsonNode 字段并将其作为字符串存储在数据库中,然后当我从 table 中读取时它会将字符串转换回 JsonNode?
有效负载:
{
"id": "db8e8d4b-eee2-4507-bf30-f55c3f948724",
<-- Omitting extra properties -->
"metadata": {
"description": "Sample",
"location": "Stack Overflow"
}
}
现在每次我尝试保存它时都会收到错误消息:
Could not determine type for: com.fasterxml.jackson.databind.JsonNode, at table: table_name, for columns: [org.hibernate.mapping.Column(metadata)]
我遵循了这些说明: https://www.baeldung.com/hibernate-custom-types
创建了一个 SqlTypeDescriptor
public class JsonNodeStringType extends AbstractSingleColumnStandardBasicType<JsonNode> implements DiscriminatorType<JsonNode> {
public static final JsonNodeStringType INSTANCE = new JsonNodeStringType();
public JsonNodeStringType() {
super(VarcharTypeDescriptor.INSTANCE, JsonNodeStringJavaDescriptor.INSTANCE);
}
@Override
public String getName() {
return "jsonnode";
}
@Override
public JsonNode stringToObject(String xml) {
return fromString(xml);
}
@Override
public String objectToSQLString(JsonNode value, Dialect dialect) {
return '\'' + toString(value) + '\'';
}
}
然后我创建了一个 Java 类型描述符:
public class JsonNodeStringJavaDescriptor extends AbstractTypeDescriptor<JsonNode> {
public static final ObjectMapper mapper = new ObjectMapper();
public static final JsonNodeStringJavaDescriptor INSTANCE = new JsonNodeStringJavaDescriptor();
public JsonNodeStringJavaDescriptor() {
super(JsonNode.class, ImmutableMutabilityPlan.INSTANCE);
}
@Override
public String toString(JsonNode value) {
try {
return mapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("The given JsonNode object value: " + value + " cannot be transformed to a String", e);
}
}
@Override
public JsonNode fromString(String string) {
try {
return mapper.readTree(string);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("The given string value: " + string + " cannot be transformed to JsonNode object", e);
}
}
@Override
public <X> X unwrap(JsonNode value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isAssignableFrom(type)) {
return (X) toString(value);
}
throw unknownUnwrap(type);
}
@Override
public <X> JsonNode wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isInstance(value)) {
return fromString(value.toString());
}
throw unknownWrap(value.getClass());
}
然后将类型定义添加到实体模型
@Data
@TypeDef(name = "jsonnode", typeClass = JsonNodeStringType.class)
public class GenericEntity implements Serializable {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Type(type = "uuid-char")
private UUID id;
<--Omitting extra properties -->
@Type(type = "jsonnode")
private JsonNode metadata;
}
如果你不想手动创建这些类型描述符你也可以按照这篇文章使用外部依赖:https://vladmihalcea.com/sql-server-json-hibernate/