【问题标题】:How to map Postgres JSON data type in DTO and Aggentity class using Springboot and Hibernate如何使用 Springboot 和 Hibernate 在 DTO 和 Aggentity 类中映射 Postgres JSON 数据类型
【发布时间】:2020-09-14 07:19:09
【问题描述】:

我有一个 ResponseDto 类,如下所示:

public static class HealthGoalsHighlight {

    @ApiModelProperty(value = "Total number of eligible users")
    private Long totalEligibleUsers;
    @ApiModelProperty(value = "Total number of registered users")
    private Long totalRegisteredUsers;
    @ApiModelProperty(value = "Total number of users with atleast one goal count")
    private Long totalUsersWithGoal;
    @ApiModelProperty(value = "Top goal name selected by user")
    private String topGoal;
    @ApiModelProperty(value = "Bottom goal name selected by user")
    private String bottomGoal;
  }

此 DTO 是根据下表结构制作的:

health_goals
(
  uid BIGSERIAL NOT NULL CONSTRAINT health_goals_pkey primary key,
  employer_key bigint not null,
  total_eligible_users bigint not null,
  total_registered_users bigint not null,
  total_users_with_goal bigint not null,
  top_goal_name varchar(255),
  bottom_goal_name varchar(255),
  created_ts TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_ts TIMESTAMP NOT NULL DEFAULT NOW(),
  created_by varchar(255),
  updated_by varchar(255)
);

现在表结构已更改为:

health_goals
(
  uid BIGSERIAL NOT NULL CONSTRAINT health_goals_pkey primary key,
  employer_key bigint not null,
  health_goals_metric_value json null,
  created_ts TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_ts TIMESTAMP NOT NULL DEFAULT NOW(),
  created_by varchar(255),
  updated_by varchar(255)
);

现在基本上所有这些列,如total_eligible_userstotal_registered_userstotal_users_with_goaltop_goal_namebottom_goal_name 将被合并为单个列health_goals_metric_value 作为 JSON 数据类型。

如何为 JSON 数据类型列编写响应 DTO。另外,我的 AggMapper 类中需要进行哪些更改。

【问题讨论】:

  • 请分享您现有的 AggMapper 类的代码。

标签: java json hibernate spring-boot spring-mvc


【解决方案1】:

一种方法是使用转换器功能。您可以使用转换器函数来获取相同格式的值。

在您的列定义中更改您的orm.xml 如下所示

<basic name="healthGoalsMetricValue">
                <column name="health_goals_metric_value" nullable="true"/>
                <convert converter="path.to.your.HealthGoalsMetricValueConverter"/>
            </basic>

或者如果你有java文件

代理将有以下条目

  @Convert(converter = HealthGoalsMetricValueConverter.class)
    private HealthGoalsHighlight healthGoalsHighlight ;

你的班级 HealthGoalsMetricValue 看起来像

////////////////在cmets之后编辑转换器类

       import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.io.IOException;

@Converter
public class HealthGoalsMetricValueConverter implements AttributeConverter<HealthGoalsMetricValue, String> {

private final ObjectMapper mapper = new ObjectMapper();

//And then override like that
@Override
        public String convertToDatabaseColumn(HealthGoalsHighlight healthGoalsMetricValue) {

            try {                
                json = mapper.writeValueAsString(healthGoalsMetricValue);
            } catch (JsonProcessingException exception) {
                throw new JsonProcessingException("Error occurred while object serialization", exception);
            }
            return json;
    }

 //And then override again
@Override
public HealthGoalsMetricValue  convertToEntityAttribute(String healthGoalsMetricValuestr ) {
    HealthGoalsMetricValue  healthGoalsMetricValue  = null;
    try {
        if (healthGoalsMetricValue != null) {
            healthGoalsMetricValue = mapper.readValue(healthGoalsMetricValuestr, HealthGoalsMetricValue.class);
        }
    } catch (Exception exception) {
        throw new Exception("Error occurred while object Deserialization", exception);
    }
    return healthGoalsMetricValue;
}

这一切都将为您完成工作。

【讨论】:

  • convertToDatabaseColumn(HealthGoalsMetricValue healthGoalsMetricValue) -- 在这个方法“HealthGoalsMetricValue”中,我应该在哪里定义这个类以及它的内容。否则它给我错误,无法解析符号 HealthGoalsMetricValue。
  • 这将是实体类中 JSON cloumn 的类型。HealthGoalsHighlight@sandeep
  • @Sandeep 如果仍有疑问,请告诉我。
  • 我想我把一切都搞砸了。得到很多错误。让我试着一步一步写到这里。这就是 mu DTO 的样子。公共类 HealthGoalsHighlightResponseDto 实现 Serializable { private MetadataDto 元数据;私人健康目标突出健康目标突出; @EqualsAndHashCode 公共静态类 HealthGoalsHighlight { @ApiModelProperty(value = "Total metrics") private Map healthGoalsMetricValue; } }
  • 这是我的 AggEntity 类 public class HealthGoalsHighlightAggEntity extends AggBaseEntity { @Convert(converter = HealthGoalsMetricValueConverter.class) private HealthGoalsHighlight healthGoalsHighlight ; }
【解决方案2】:

如果您可以添加其他库,请查看 https://github.com/vladmihalcea/hibernate-types 项目,这非常容易。

有了这个库,你最终会得到像这样简单的代码

@Entity
@Table(name = "health_goals")
@TypeDefs({
    @TypeDef(name = "json", typeClass = JsonStringType.class),
    @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class HealthGoal {
    // all other columns
    @Type(type = "json")
    private HealthGoalsHighlight healthGoalsHighlight;

    // getters setters

}

如果使用maven添加依赖

<dependency>
  <groupId>com.vladmihalcea</groupId>
  <artifactId>hibernate-types-52</artifactId>
  <version>2.9.10</version> // or newer version
</dependency>

【讨论】:

  • 我没有使用 Maven。我该如何使用这个库。我需要下载并安装在我的项目中吗?如果是,该怎么做。
  • @sandeep 只需将 部分添加到您的 pom.xml 中。并将@TypeDefs 放在您的实体上,将@Type 放在字段上,您就可以开始了。看到这个很酷的文档vladmihalcea.com/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
相关资源
最近更新 更多