当前使用版本(必须填写清楚,否则不予处理)

3.3.0 自带的FastjsonTypeHandler配合@TableField处理字段时无法正确处理List<?>类型的数据, 查询时全部处理成了List,这会在遍历列表获取某个属性时发生强转JSONObject->?,发生类型转换报错

该问题是怎么引起的?(最新版上已修复的会直接close掉)

假设有个List<Demo>类型的属性注解了@TableField 在MP构造TableFieldInfo时只获取了List作为属性类型,所以在调用getResultMapping方法注册TypeHandler时只是把List.class传入

public class TableFieldInfo implements Constants {
……
public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField) {
        ……
        this.propertyType = field.getType();
        ……
}
……
ResultMapping getResultMapping(final MybatisConfiguration configuration) {
        ……
        typeHandler = registry.getInstance(propertyType, this.typeHandler);
        ……
}
……
}

建议

给TableFieldInfo新增一个泛型属性genericType,构造时this.genericType=field.getGenericType(),注册时typeHandler = registry.getInstance(propertyType, genericType, this.typeHandler); 这样方便在FastjsonTypeHandler处理时获取到泛型直接调用JSON.parseObject(json, genericType);完成转换

Comment From: miemieYaho

内置 jsonTypeHandler 不适用于 list或 map或set

Comment From: nasodaengineer

内置 jsonTypeHandler 不适用于 list或 map或set

我知道不适用,所有建议加个泛型属性,这样我自定义的一个TypeHandler时也方便转换

Comment From: junxy

使用 数组代替泛型集合 可避坑

Comment From: simplechen

新版本已经支持 spring boot pom.xml 部署配置 mysql mysql-connector-java runtime com.alibaba druid 1.2.11

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.83</version>
    </dependency>

@Data public class KVNode implements Serializable {

private String key;

private String val;

private List<KVNode> nodes;

}

public class AppInfo implements Serializable {

private static final long serialVersionUID = 1L;

/**
 * id
 */
  @TableId(value = "id", type = IdType.AUTO)
private Integer id;

/**
 * 应用名称
 */
private String name;

/**
 * 应用属性
 * 经验证 JacksonTypeHandler FastjsonTypeHandler都可以使用
 */

// @TableField(value="properties",typeHandler = JacksonTypeHandler.class) @TableField(value="properties",typeHandler = FastjsonTypeHandler.class) private List properties; }


控制器中使用 @RestController @RequestMapping("/app") public class AppInfoController {

@Autowired
private AppInfoMapper mapper;

@RequestMapping("/list") public List list() { return mapper.selectList(null); } }


使用URL访问控制器输出 [ { id: 1, name: "sss", properties: [ { val: "shenzhen", nodes: null, key: "city" }, { val: "guangzhou", nodes: null, key: "city" } ] }, { id: 2, name: "sss", properties: [ { val: "shenzhen", nodes: null, key: "city" }, { val: "guangzhou", nodes: null, key: "city" } ] }, { id: 3, name: "sss", properties: [ { val: "shenzhen", nodes: null, key: "city" }, { val: "guangzhou", nodes: null, key: "city" } ] }, { id: 4, name: "sss", properties: [ { val: "shenzhen", nodes: [ ], key: "city" }, { val: "guangzhou", nodes: [ ], key: "city" } ] }, { id: 5, name: "sss", properties: [ { val: "shenzhen", nodes: [ ], key: "city" }, { val: "guangzhou", nodes: [ ], key: "city" } ] }, { id: 6, name: "sss", properties: [ { val: "shenzhen", nodes: [ ], key: "city" }, { val: "guangzhou", nodes: [ ], key: "city" } ] }, { id: 7, name: "sss", properties: [ { val: "shenzhen", nodes: [ ], key: "city" }, { val: "guangzhou", nodes: [ ], key: "city" } ] } ]


@MappedTypes({Object.class}) @MappedJdbcTypes(JdbcType.VARCHAR) public class JsonTypeHandler extends BaseTypeHandler { // private final static Log log = LogFactory.getLog(JsonTypeHandler.class); private static ObjectMapper objectMapper; private Class type; static { objectMapper = new ObjectMapper(); }

public JsonTypeHandler(Class<T> type) {
    if(log.isTraceEnabled()) {
        log.trace("JsonTypeHandler(" + type + ")");
    }
    if (type == null) {
        throw new IllegalArgumentException("Type argument cannot be null");
    }
    this.type = type;
}

private  T parse(String json) {
    try {
        if(json == null || json.length() == 0) {
            return null;
        }
        return objectMapper.readValue(json, type);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private String toJsonString(Object obj) {
    try {
        return objectMapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
}

@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
    return (T) parse(rs.getString(columnName));
}

@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    return (T) parse(rs.getString(columnIndex));
}

@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    return (T) parse(cs.getString(columnIndex));
}

@Override
public void setNonNullParameter(PreparedStatement ps, int columnIndex, T parameter, JdbcType jdbcType) throws SQLException {
    ps.setString(columnIndex, toJsonString(parameter));

}

}