Использование jsonb

Если в jmix использовать динамически Map<String, Object> attr в jsonb для psql, если да как я могу это сделать скажите плз?)

Добрый день,

Jmix из коробки не поддерживает jsonb, тк такой тип не является кроссплатформенным для разных СУБД. Однако, добавить его не сложно в проект.

Первый способ:

  1. Создаем changeset, держим в голове, что не все СУБД поддерживает такой тип колонки:

        <changeSet id="1" author="jsonbtest">
            <addColumn tableName="USER_">
                <column name="LOCATION" type="jsonb" defaultValue="{}"/>
            </addColumn>
        </changeSet>
    

    Просто добавляем колонку с типом jsonb.

  2. Добавляем в проект DTO JsonB дженерик типа:

    @JmixEntity(annotatedPropertiesOnly = true)
    public class JsonB {
        private Map<String, Object> container = new HashMap<>();
    
        public Map<String, Object> getContainer() {
            return container;
        }
    
        public void setContainer(Map<String, Object> container) {
            this.container = container;
        }
    }
    

    Здесь стоит отметить обязательность @JmixEntity(annotatedPropertiesOnly = true), так мы обеспечиваем себе метаданные для Jmix для типа JsonB и одновременно с этим игнорируем Map<String, Object>, чтобы оно не попало в мета данные, ведь мы сами в ручную будем ее записывать в базу (при помощи ObjectMapper будем весь класс marshal -ить в json)

  3. Добавляем JPA Converter:

@Converter(autoApply = true)
public class JsonbConverter implements AttributeConverter<JsonB, PGobject> {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public PGobject convertToDatabaseColumn(JsonB attribute) {
        PGobject result = new PGobject();
        String jsonbResult;
        result.setType("jsonb");
        try {
            jsonbResult = objectMapper.writeValueAsString(attribute);
            result.setValue(jsonbResult);
        } catch (Exception e) {
        }
        return result;
    }

    @Override
    public JsonB convertToEntityAttribute(PGobject dbData) {
        if(dbData == null || !dbData.getType().equals("jsonb") || dbData.getValue() == null){
            return new JsonB();
        }
        try {
            return objectMapper.readValue(dbData.getValue(), JsonB.class);
        } catch (JsonProcessingException e) {
            return new JsonB();
        }
    }
}
  1. Добавляем наш тип в любую сущность, например, User:
    @Convert(converter = JsonbConverter.class)
    @Column(name = "LOCATION")
    private JsonB location = new JsonB();

Вот и все, теперь в проекте есть jsonb с типом Map<String, Object>. Ссылка на демо проект - GitHub - KartnDev/jsonbjmix: This is example how to use Postgres's JsonB with Jmix and JPA

Альтернативный вариант:

Альтернативный вариант вместо JmixEntity DTO можно создать JPA DateType через аннотацию, и даже можно унастледоваться от Map<String, Object> или использоваться паттерн декоратор, из за чего год будет на 1 вложенную сущность меньше (вместо выражения entity.getJsonB().getContainer().get("key") будет entity.getJsonB().get("key"))

С уважением,
Дмитрий

2 симпатии