Чтение JSON из БД с помощью myBatis

У меня есть столбец в БД, я хочу сохранить его как JSON и получить обратно.

Мой подход:

Я сохраняю его как ClobTypeHandler и пытаюсь восстановить как ClobTypeHandler.

Я использую Mybatis, но получаю ошибку ниже.

Could not set property 'idType' of 'class package.abc' with value '{"idNum":"123","text":"ENCkk-KZJTmN8Mr5jEims0rssRow8xaAnkOtl0RQHDth1ByVtshI7zQebtcogOvYM-gNo15DwwPmduaufk03CteqRL03cRyrG4%3B","key":"}P]H73}AF}TGB$OIDCYVIIB+VW{4TR)I?U}_`_ZXP[UY$BJNXV{U~/@!F%+SVMFYT/2IAXIOPB"}' Cause: java.lang.IllegalArgumentException: argument type mismatch

Ниже показан уровень Java и детали БД.

class abc{

    private JsonNode idType;

    public String getIdType() {
         return idType != null ? idType.toString():null;
    }
    public void setIdType(JsonNode idType) {
        this.idType = idType;
    }
}

mapper.xml (вставка в БД)

INSERT INTO CUSTOMER
    (<include refid = "common_customer_insert_columns"></include>,id_type)        
 VALUES
    (<include refid = "common_customer_insert_fields"></include>,<include refid = "cc_customer_insert_fields"></include>,
        <choose> <when test = "abc.idType !=null">#{abc.idType,typeHandler= org.apache.ibatis.type.ClobTypeHandler}</when>
                <otherwise>''</otherwise></choose>);

mapper.xml (при чтении из БД)

<resultMap>
    <result column = "id_type" property = "abc.idType" 
        typeHandler = "org.apache.ibatis.type.ClobTypeHandler" />
</resultMap>

образец значения JSON, который я пытаюсь сохранить и получить:

"idType": {  
       "idNum": "123",  
       "text": "ENh-KZJTmN8Mr5jEims0rssRow8xaADth1ByVtshI7zQebtcogOvYM-gNo15DwwPmduaufk03CteqRLaVwF0b3cRyrG4%3D",  
       "key":"}P]H73}AF}TGB$OICQ*DCYVIIB+VW{4TR)I?U}_`_ZXP[UY$BJNXV{@!F%+SVMFYT/2IAXIOPB"  
      }  

любое обновление по этому поводу, сталкивающееся с той же проблемой

yolob 21 27.05.2019 09:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
1
7 799
2

Ответы 2

Вы можете сделать это без использования POJO:

ObjectMapper mapper = new ObjectMapper();
JsonNode idType = mapper.readTree(<json-string>);

да, но мне нужен POJO, так как есть дополнительные поля, которые POJO состоит вместе с этим полем

user10382836 19.09.2018 19:20

ClobTypeHandler расширяет BaseTypeHandler<String>, так что он позволяет устанавливать и извлекать значение из столбца базы данных как String. Когда вы используете ClobTypeHandler вот так:

#{abc.idType,typeHandler= org.apache.ibatis.type.ClobTypeHandler}

mybatis под капотом ожидает, что abc.getIdType вернет String, что он и делает. Все идет нормально.

Когда вы извлекаете значение из базы данных, используется сопоставление:

<result column = "id_type" property = "abc.idType"
     typeHandler = "org.apache.ibatis.type.ClobTypeHandler" />

В этом случае ClobTypeHandler пытается установить свойство idType с помощью установщика setIdType и ожидает, что он примет String. Но аргумент установщика - JsonNode, поэтому вы получите сообщение о несовместимости типа.

Чтобы исправить это изменение, установщик типов получает и выполняет в нем преобразование из String в JsonNode:

public void setIdType(String idTypeString) {
     ObjectMapper mapper = new ObjectMapper();
     this.idType = mapper.readTree(isTypeString);
}

Примечание: вы можешь использовать static ObjectMapper, чтобы избежать его создания при каждом вызове.

Лучше создать твой собственныйTypeHandler для типа JsonNode. Он будет выполнять преобразование String <=> JsonNode внутренне, чтобы ваш abc не был загрязнен этой (несвязанной) логикой.

После изменения метода установки с помощью objectMapper я получаю следующую ошибку: - package.abc ["idType"]) "error = " com.fasterxml.jackson.databind.JsonMappingException - Невозможно десериализовать экземпляр java.lang.String вне Токен START_OBJECT

user10382836 19.09.2018 17:32

Другие вопросы по теме