如何使用杰克逊和jdbc从json对象转换为数据库表行插入?

问题描述

我有一个反序列化的json对象:

TypeReference<HashMap<String,Object>> typeRef
        = new TypeReference<HashMap<String,Object>>() {};

HashMap<String,Object> map = objectMapper.readValue(json,typeRef);

重要说明:没有要映射的java类(类型仅由数据库知道)

我能够从数据库模式中获取类型:

public static List<TableColumnTypeMap> getTableColumns(DataSource dataSource,String schema,String tableName) {
    try {
        return (List<TableColumnTypeMap>) JdbcUtils.extractDatabaseMetaData(dataSource,dbmd -> {
                    ResultSet rs = dbmd
                            .getColumns(null,schema,tableName,null);
                    List<TableColumnTypeMap> list = new ArrayList<>();
                    while (rs.next()) {

                        String columnName = rs.getString("COLUMN_NAME");
                        String typeName = rs.getString("TYPE_NAME");
                        int dataType = rs.getInt("DATA_TYPE");

                        TableColumnTypeMap tableColumnTypeMap = new TableColumnTypeMap()
                                .setColumnName(columnName)
                                .setColumnType(typeName)
                                .setsqlType(dataType);
                        list.add(tableColumnTypeMap);
                    }

                    return list;
                });
    }
    catch (MetaDataAccessException ex) {
        throw new IllegalStateException("get table list Failed",ex);
    }
}

所以我能够知道地图中每个对象的类型。

我如何告诉杰克逊“嘿,这个地图项目是这种类型的?”

然后我将能够:

jdbcTemplate.update("<insert statement>",objs);

其中objs是“存储”为对象但类型正确的对象数组。

解决方法

我已将所有内容转换为String并通过此方法获取:

private Object getObject(TableColumnTypeMap tableCol,String val) {
    switch (tableCol.getSqlType()) {
        case Types.BIT:
        case Types.BOOLEAN:
            return Boolean.parseBoolean(val);
        case Types.DECIMAL:
        case Types.DOUBLE:
        case Types.FLOAT:
        case Types.NUMERIC:
        case Types.REAL:
            return new BigDecimal(val);
        case Types.BIGINT:
            return Long.parseLong(val);
        case Types.INTEGER:
            return Integer.parseInt(val);
        case Types.SMALLINT:
            return Short.parseShort(val);
        case Types.TINYINT:
            return Byte.parseByte(val);
        case Types.DATE:
            return java.sql.Date.valueOf(LocalDate.parse(val,DateTimeFormatter.ISO_DATE));
        case Types.TIMESTAMP:
            try {
                return Timestamp.valueOf(LocalDateTime.parse(val,DateTimeFormatter.ISO_DATE_TIME));
            }
            catch (DateTimeParseException e) {
                return java.sql.Date.valueOf(LocalDate.parse(val,DateTimeFormatter.ISO_DATE));
            }
        case Types.TIMESTAMP_WITH_TIMEZONE:
            return Timestamp.from(ZonedDateTime.parse(val,DateTimeFormatter.ISO_OFFSET_DATE_TIME).toInstant());
        default:
            return val;
    }
}

观察:

  • 我只使用这些类型;
  • 在json上,日期格式为iso日期;