上班学习就是快,各种奇怪的需求提的我眼花缭乱。废话不多说,直接开搞
已知需求是设计一张问卷表,目前问卷的问题类型只有单选题,怎么设计表和库。
问题表类似下面
疼痛分级 | 描述 | 分数 |
---|---|---|
0 | 无痛 | 0 |
1 | 微痛 | 2 |
2 | 剧痛 | 4 |
一个问题下面有多个选项,每个选项有不同的分值,用于最后计算问卷的最终得分。
如果建单表,会非常复杂而且逻辑不清晰,不如把问题抽出来
选项表
/**
* 选项的描述
*/
private String description;
/**
* 选项的分数
*/
private Integer score;
然后在数据库直接保存 json,日后扩展也简单了。
那么怎么保存 json 到数据库呢?
问卷表
//问卷ID
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
//问题名称
private String name;
private Integer typeId;
//选项1,对应选项表
private OptionDto op1;
很简单,直接 fast json 一把梭,重写问卷表的特定字段的 set 方法即可
public void setOp1(OptionDto dto) {
//将OptionDto对象转换为JSON字符串
this.op1 = JSON.toJSONString(dto);
}
这样就能将 OptionDto 转为 json 存到数据库了。
但是,当我从数据库取数据时,会发现 OptionDto 数据变为 null 了,明明查询语句是没问题的,SQL 也能查出来,但是就是赋不了值。
这是因为 mybatis-plus 无法处理我们自定义的数据类型,我们数据库是 VARCHAR,但是代码里却不是 String,所以赋不了值。
Type Hnadel#
好消息是,mybatis-plus 提供了自定义的类型处理类,来处理代码和数据库之间的数据流转,就是 TypeHandle
要使用 typeHandel,需要在配置文件配置
# 配置自定义类型转换器的包路径
mybatis-plus.type-handlers-package=xyz.qinfengge.handel
然后配置处理类
@MappedTypes({OptionDto.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class OptionsTypeHandel extends BaseTypeHandler<OptionDto> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, OptionDto optionDto, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, optionDto.toString());
}
@Override
public OptionDto getNullableResult(ResultSet resultSet, String s) throws SQLException {
return resultSet.getString(s) == null ? null : str2Dto(resultSet.getString(s));
}
@Override
public OptionDto getNullableResult(ResultSet resultSet, int i) throws SQLException {
return resultSet.getString(i) == null ? null : str2Dto(resultSet.getString(i));
}
@Override
public OptionDto getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return callableStatement.getString(i) == null ? null : str2Dto(callableStatement.getString(i));
}
//把String转为OptionDto
public static OptionDto str2Dto(String string) {
//将JSON字符串转换为OptionDto对象
return JSON.parseObject(string, OptionDto.class);
}
}
@MappedTypes
中填写的是我们代码中的数据类型@MappedJdbcTypes
中填写的是数据库中的数据类型
重写里面的 4 个方法,第一个方法是保存数据,所以直接 optionDto.toString () 保存到数据库,下面三个方法是查询语句,要把 json 转为对象,如果不写,就是 null。
最后指定实体类中自定义数据类型使用的类型解析器
//问卷ID
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
//问题名称
private String name;
private Integer typeId;
//选项1,对应选项表
//指定类型解析器
@TableField(typeHandler = OptionsTypeHandel.class)
private OptionDto op1;
这样就 OK 了。