如何使用 H2、JPA 和 Hibernate 映射 JSON 列

新手上路,请多包涵

我在应用程序 MySQL 5.7 中使用,并且有 JSON 列。当我尝试运行时,我的集成测试不起作用,因为 H2 数据库无法创建表。这是错误:

 2016-09-21 16:35:29.729 ERROR 10981 --- [           main] org.hibernate.tool.hbm2ddl.SchemaExport  : HHH000389: Unsuccessful: create table payment_transaction (id bigint generated by default as identity, creation_date timestamp not null, payload json, period integer, public_id varchar(255) not null, state varchar(255) not null, subscription_id_zuora varchar(255), type varchar(255) not null, user_id bigint not null, primary key (id))
2016-09-21 16:35:29.730 ERROR 10981 --- [           main] org.hibernate.tool.hbm2ddl.SchemaExport  : Unknown data type: "JSON"; SQL statement:

这是实体类。

 @Table(name = "payment_transaction")
public class PaymentTransaction extends DomainObject implements Serializable {

    @Convert(converter = JpaPayloadConverter.class)
    @Column(name = "payload", insertable = true, updatable = true, nullable = true, columnDefinition = "json")
    private Payload payload;

    public Payload getPayload() {
        return payload;
    }

    public void setPayload(Payload payload) {
        this.payload = payload;
    }
}

和子类:

 public class Payload implements Serializable {

    private Long userId;
    private SubscriptionType type;
    private String paymentId;
    private List<String> ratePlanId;
    private Integer period;

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public SubscriptionType getType() {
        return type;
    }

    public void setType(SubscriptionType type) {
        this.type = type;
    }

    public String getPaymentId() {
        return paymentId;
    }

    public void setPaymentId(String paymentId) {
        this.paymentId = paymentId;
    }

    public List<String> getRatePlanId() {
        return ratePlanId;
    }

    public void setRatePlanId(List<String> ratePlanId) {
        this.ratePlanId = ratePlanId;
    }

    public Integer getPeriod() {
        return period;
    }

    public void setPeriod(Integer period) {
        this.period = period;
    }

}

这个用于插入数据库的转换器:

 public class JpaPayloadConverter implements AttributeConverter<Payload, String> {

    // ObjectMapper is thread safe
    private final static ObjectMapper objectMapper = new ObjectMapper();

    private Logger log = LoggerFactory.getLogger(getClass());

    @Override
    public String convertToDatabaseColumn(Payload attribute) {
        String jsonString = "";
        try {
            log.debug("Start convertToDatabaseColumn");

            // convert list of POJO to json
            jsonString = objectMapper.writeValueAsString(attribute);
            log.debug("convertToDatabaseColumn" + jsonString);

        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage());
        }
        return jsonString;
    }

    @Override
    public Payload convertToEntityAttribute(String dbData) {

        Payload payload = new Payload();
        try {
            log.debug("Start convertToEntityAttribute");

            // convert json to list of POJO
            payload = objectMapper.readValue(dbData, Payload.class);
            log.debug("JsonDocumentsConverter.convertToDatabaseColumn" + payload);

        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
        return payload;

    }
}

原文由 earandes 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

JSON 支持是在问题提出后添加到 H2 的,版本为 1.4.200 (2019-10-14)。

但是,您很少需要数据库中的 JSON 数据类型。 JSON 本质上只是一个可能很长的字符串,因此您可以使用大多数数据库都提供的 CLOB。

如果您需要对它们进行操作的 SQL 函数,那么您确实需要 JSON 数据类型,并且仅当数据库坚持其 JSON 函数对 JSON 类型而不是 CLOB 进行操作时。但是,此类功能往往依赖于数据库。

原文由 toolforger 发布,翻译遵循 CC BY-SA 4.0 许可协议

我刚刚在使用 JSONB 列类型时遇到了这个问题 - JSON 类型的二进制版本,它没有映射到 TEXT

为了将来参考,您可以使用 CREATE DOMAIN 在 H2 中定义自定义类型,如下所示:

 CREATE domain IF NOT EXISTS jsonb AS other;

这似乎对我有用,并允许我针对该实体成功测试我的代码。

资料来源: https ://objectpartners.com/2015/05/26/grails-postgresql-9-4-and-jsonb/

原文由 n00dle 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题