1
resposta

Salvar Json no PostgreSQL com Spring

Olá!

Estou tentando mapear um campo chamdo "fields" do tipo JSONB no Postgres na minha classe de entidade do spring boot 3.3.3, mas está gerando erro na compilação.

Minha classe de entidade:

package com.meusite.api.entity;

import java.time.LocalDateTime;

import com.meusite.api.enums.Status;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.JsonNode;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import jakarta.validation.constraints.NotNull;
import lombok.Data;



@Data
@Entity

public class DocumentModel {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime dateCreated = LocalDateTime.now();

    @Temporal(TemporalType.TIMESTAMP)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime dateUpdated;

    @Column(length = 200, nullable = false)
    private String name;

    private String description;

    private JsonNode fields;

    @ManyToOne(optional = false)
    @JoinColumn(name = "company_id")
    private Company company;

    @NotNull(message = "Status nao deve ser nulo")
    @Enumerated(EnumType.STRING)
    private Status status = Status.ACTIVE;
}

Qual seria a maneira correta de mapear o campo?

1 resposta

Olá Deise! Tudo bem?

Para mapear corretamente um campo do tipo JSONB no PostgreSQL usando Spring Data JPA, você pode utilizar a anotação @TypeDef do Hibernate. No seu caso, você já está utilizando JsonNode da biblioteca Jackson para representar o campo JSON. Vamos ajustar a sua entidade para que o campo fields seja mapeado corretamente.

Aqui está como você pode fazer isso:

  1. Adicione a dependência do Hypersistence Utilities Hibernate no seu pom.xml para suportar JSONB:

    <dependency>
        <groupId>io.hypersistence</groupId>
        <artifactId>hypersistence-utils-hibernate-55</artifactId>
        <version>3.8.2</version>
    </dependency>
    
  2. Atualize a sua classe DocumentModel para usar a anotação @TypeDef do Hibernate:

    package com.meusite.api.entity;
    
    import java.time.LocalDateTime;
    import com.meusite.api.enums.Status;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import com.fasterxml.jackson.databind.JsonNode;
    import jakarta.persistence.Column;
    import jakarta.persistence.Entity;
    import jakarta.persistence.EnumType;
    import jakarta.persistence.Enumerated;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import jakarta.persistence.JoinColumn;
    import jakarta.persistence.ManyToOne;
    import jakarta.persistence.Temporal;
    import jakarta.persistence.TemporalType;
    import jakarta.validation.constraints.NotNull;
    import lombok.Data;
    import org.hibernate.annotations.Type;
    
    @Data
    @Entity
    @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
    public class DocumentModel {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @NotNull
        @Temporal(TemporalType.TIMESTAMP)
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime dateCreated = LocalDateTime.now();
    
        @Temporal(TemporalType.TIMESTAMP)
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime dateUpdated;
    
        @Column(length = 200, nullable = false)
        private String name;
    
        private String description;
    
        @Type(type = "jsonb")
        @Column(name = "address", columnDefinition = "jsonb")
        private JsonNode fields;
    
        @ManyToOne(optional = false)
        @JoinColumn(name = "company_id")
        private Company company;
    
        @NotNull(message = "Status nao deve ser nulo")
        @Enumerated(EnumType.STRING)
        private Status status = Status.ACTIVE;
    }
    

Com essas mudanças, o campo fields será mapeado como JSONB no PostgreSQL, e você deve conseguir salvar e recuperar objetos JSON sem problemas.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.