【问题标题】:Reading a JSON from DB with myBatis使用 myBatis 从 DB 中读取 JSON
【发布时间】:2019-02-23 02:10:48
【问题描述】:

我在 DB 中有一个列,我想将其保存为 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层和DB细节。

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(从 DB 读取时)

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

【问题讨论】:

  • 对此的任何更新,面临同样的问题

标签: java json mybatis


【解决方案1】:

您可以在不使用 POJO 的情况下做到这一点:

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

【讨论】:

  • 是的,但我需要 POJO,因为 POJO 包含与此字段一起的其他字段
【解决方案2】:

ClobTypeHandler 扩展了BaseTypeHandler&lt;String&gt;,因此它允许将数据库列中的值设置和检索为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 尝试使用setIdType 设置器设置idType 属性,并希望它接受String。但是 setter 参数是 JsonNode,因此您会收到类型不兼容的消息。

要修复此更改,类型设置器获取并在其中进行从 StringJsonNode 的转换:

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

注意:你 can use 静态 ObjectMapper 以避免在每次调用时创建它。

更好的方法是为类型JsonNode 创建your own TypeHandler。它会在内部进行String JsonNode 转换,因此您的abc 不会被这个(不相关的)逻辑所污染。

【讨论】:

  • 使用 objectMapper 修改我的 setter 方法后出现以下错误:- package.abc["idType"])" error="com.fasterxml.jackson.databind.JsonMappingException - 无法反序列化实例START_OBJECT 令牌中的 java.lang.String
【解决方案3】:

要将数据(Pojo 类)保存为 JSON 值并读取为 POJO 类,我们需要编写自定义 TypeHandler

假设我们有一个 Employee 类,其中配置对象需要在数据库中保存为 JSON 并读取为配置对象

Employee.java

public class Employee {
    private int id;
    private String name;
    private Config config; //save as josn in DB
}

Config.java

public class Config implements Serializable{
        private static final long serialVersionUID = 1L;
        private String key;
        private String value;
        private String msg;
        private int referenceNumber;
}

JsonTypeHandler.java

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


@MappedTypes({Config.class})
public class JsonTypeHandler extends BaseTypeHandler<Config>  {

    ObjectMapper objectMapper = new ObjectMapper();

    
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Config config, JdbcType jdbcType) throws SQLException {
        try {
            preparedStatement.setObject(i, objectMapper.writeValueAsString(config));

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Config getNullableResult(ResultSet resultSet, String s) throws SQLException {
        if(resultSet.getString(s) != null){
            try {
                return objectMapper.readValue(resultSet.getString(s), Config.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Config getNullableResult(ResultSet resultSet, int i) throws SQLException {
        if(resultSet.getString(i) != null){
            try {
                return objectMapper.readValue(resultSet.getString(i), Config.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Config getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        if(callableStatement.getString(i) != null){
            try {
                return objectMapper.readValue(callableStatement.getString(i), Config.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

MyBatis 插入查询

@Insert("insert into employee(name, config) values(#{employee.name}, #{employee.config, typeHandler=com.example.demo.image.JsonTypeHandler})")
    void saveEmployee(@Param("employee") Employee employee);

MyBatis 选择查询

@Results({
            @Result(property = "id", column = "id"),
            @Result(property = "name", column = "name"),
            @Result(property = "config", column = "config", typeHandler =com.example.demo.image.JsonTypeHandler.class),

    })
    @Select("select id, name, config from employee")
        List<Employee> getAll();

【讨论】:

    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    相关资源
    最近更新 更多