Как сопоставить тип данных Postgres JSON в классе DTO и Aggentity с помощью Springboot и Hibernate - PullRequest
1 голос
/ 27 мая 2020

У меня есть класс 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_users, total_registered_users, total_users_with_goal, top_goal_name, bottom_goal_name, будут объединены в один столбец health_goals_metric_value как JSON тип данных.

Как мне написать ответный DTO для столбца с типом данных JSON. Также какие изменения нужно сделать в моем классе AggMapper.

Ответы [ 2 ]

2 голосов
/ 29 мая 2020

Один из способов - использовать функцию конвертера. Вы можете использовать функцию конвертера для получения значений в том же формате.

Измените свой orm.xml как показано ниже в определении столбца

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

Или, если у вас есть java файл

aggentity будет иметь следующую запись

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

, и ваш класс HealthGoalsMetricValue будет выглядеть примерно как

//////////////// // Отредактированный класс конвертера после комментариев

       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;
}

Все это сделает работу за вас.

0 голосов
/ 29 мая 2020

Если вы можете добавить дополнительную библиотеку, посмотрите проект 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>
...