Reputation: 921
I have micronaut application using Postgres DB. Recently I needed to add JSONB field to my table.
But I couldn't find any working solution for my case. So here's my code:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.inject.Singleton;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import java.util.List;
@Singleton
@RequiredArgsConstructor
@Converter(autoApply = true)
public class JsonbConverter implements AttributeConverter<List<Metadata>, String> {
private final ObjectMapper objectMapper;
@Override
public String convertToDatabaseColumn(List<Metadata> attribute) {
try {
return attribute == null ? null : objectMapper.writeValueAsString(attribute);
} catch (JsonProcessingException e) {
throw new RuntimeException("Error converting to JSON", e);
}
}
@Override
public List<Metadata> convertToEntityAttribute(String dbData) {
try {
return dbData == null ? null : objectMapper.readValue(dbData,
objectMapper.getTypeFactory().constructCollectionType(List.class, Metadata.class));
} catch (IOException e) {
throw new RuntimeException("Error parsing JSON", e);
}
}
}
Here's my Metadata. By the way, I tried Map<String, String> and Map<String, Object>. Nothing worked.
@Data
@Introspected
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(title = METADATA_TITLE, description = METADATA_DESCRIPTION)
public class Metadata {
@NotBlank
@Size(min = 1, max = 1000)
private String field;
@NotBlank
@Size(min = 1, max = 1000)
private String value;
@JsonCreator
public Metadata(@JsonProperty("field") String field,
@JsonProperty("value") String value) {
this.field = field;
this.value = value;
}
}
And here's my entity object where I store my fields:
@Value
@Embeddable
class StoredIndexingDetails {
@Nullable
// @Convert(converter = JsonbConverter.class)
@TypeDef(type = DataType.JSON, converter = JsonbConverter.class)
// @Column(name = "indexing_primary_metadata", columnDefinition = "jsonb")
List<Metadata> primaryMetadata;
}
As mentioned previously, tried different approaches. Tried to add
@Column(name = "indexing_primary_metadata", columnDefinition = "jsonb")
.
My error is next:
Error executing PERSIST: ERROR: column \"indexing_primary_metadata\" is of type jsonb but expression is of type character varying\n Hint: You will need to rewrite or cast the expression.
I also tried to add @ColumnTransformer(write = "?::jsonb")
Code didn't throw error, but in db field was null.
Any suggestions?
Upvotes: 0
Views: 69
Reputation: 921
I've managed to resolve the issue. So, basically, my solution with @TypeDef(type = DataType.JSON, converter = JsonbConverter.class) seems to be working. The reason I received null in my table was because in my code this field was null because of the issue with nested entity.
For those, who tries to find solution:
@Column(columnDefinition = "json", name = "test_field")
@TypeDef(type = DataType.JSON, converter = JsonbConverter.class)
final List<Metadata> testField;
The above should work. The code for JsonbConverter is in question.
Upvotes: 0