上班學習就是快,各種奇怪的需求提的我眼花繚亂。廢話不多說,直接開搞
已知需求是設計一張問卷表,目前問卷的問題類型只有單選題,怎麼設計表和庫。
問題表類似下面
疼痛分級 | 描述 | 分數 |
---|---|---|
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 了。