将jsonnode对象Map到sqldbjpa中的字符串字段

gblwokeq  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(429)

我得到了一个包含以下字段的sql表:

id  uniqueidentifier primary key,
<--Omitting extra fields -->
metadata  nvarchar(max)

我还有一个实体Map到它:

@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并将其作为字符串存储在表中。
如何转换jsonnode字段并将其作为字符串存储在db中,然后当我从表中读取时,它将字符串转换回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)]
bfrts1fy

bfrts1fy1#

我遵循这些指示: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/

相关问题