Mybatis-plus类型转换现场记录
场景:我们的文章需要封面吧!
封面有一张封面的,有多张封面的,或者说有3张封面的。
那么这个数据应该怎么保存呢?
如果是一张封面,直接保存到cover字段里,对吧!没有问题,也没有难度吧!
那如果是二张,三个呢?怎么保存?
分表?一对多!
文章表,封面表。一篇文章对应封面记录。
这个方法也是可以的。
那阳光沙滩是怎么做的呢?
类型转换
因为我们msyql里不支持数组/集合的数据类型,但是支持varchar类型
所以呢?
我们可以把数组转成字符串,保存到数据库里!
然后查询的时候,可以把字符串转成数组即可。
保存到数据库里的内容是这样子的:
https://imgs.sunofbeaches.com/group1/M00/00/0A/rBsADV3Y-CKAE7R9AAAe0PNEIFo946.png|https://imgs.sunofbeaches.com/group1/M00/00/0A/rBsADV3Y73aAKnjNAAFT53qLkF0823.png|https://imgs.sunofbeaches.com/group1/M00/00/0A/rBsADV3Y7zuAK8w8AABGCZQRXZQ148.png
取出来的是这样子的
如何实现
步骤一:
编写一个转换类,我这里是数组转字符串,字符串转数组。其他转换同理。
@MappedJdbcTypes(JdbcType.VARBINARY) //数据库里的数据类型
@MappedTypes({String[].class}) //java数据类型
public class CoversTypeHandler extends BaseTypeHandler<String[]> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, String[] strings, JdbcType jdbcType) throws SQLException {
String s = dealListToOneStr(strings);
preparedStatement.setString(i, s);
}
private String dealListToOneStr(String[] parameter) {
if (parameter == null || parameter.length <= 0)
return null;
StringBuilder res = new StringBuilder();
for (int i = 0; i < parameter.length; i++) {
if (i == parameter.length - 1) {
res.append(parameter[i]);
return res.toString();
}
res.append(parameter[i]).append("|");
}
return null;
}
@Override
public String[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
return resultSet.getString(s).split("\\|");
}
@Override
public String[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
return resultSet.getString(i).split("\\|");
}
@Override
public String[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return callableStatement.getString(i).split("\\|");
}
}
我使用的是|进行分割,你们可以使用逗号也是可以的。但是要求内容里没有此符号才行。
步骤二:
在bean类里添加
@TableName(value = "ct_article", autoResultMap = true)
主要是这个autoResultMap = true,value根据你的实际情况填写,这个是表名。如果类名起对应的话,那么可以不写。
对应的字段添加:
@TableField(typeHandler = CoversTypeHandler.class)
private String[] covers;
然后跑起来,进行查询,结果:
但是,这种查询适合使用api进行插叙,也就是使用mapper里自动生成的代码。
那么动态的sql语句怎么弄呢?
对应的vo类添加这个
@TableField(typeHandler = CoversTypeHandler.class)
private String[] covers;
也是添加autoResultMap = true吗?当然,不过不是在vo类上添加,而是写到mapper.xml里。
如果不加的话,会无效。
比如说这个查询:
<select id="getArticleRecommend" resultType="net.sob.content.vo.MainListItemVo">
SELECT a.`covers` ,a.`title`,,u.`avatar`,u.`is_vip`
FROM `ct_article` a LEFT JOIN `uc_user` u ON a.`user_id` = u.`id`
<where>
<if test="categoryId!=null and categoryId!=''">
a.`category_id` = #{categoryId}
</if>
</where>
ORDER BY a.`create_time` LIMIT #{offset},#{size};
</select>
很明显,结果是为null的。
那要怎么改呢?
如下:
<select id="getArticleRecommend" resultMap="MainListItemVo">
SELECT a.`covers`,a.`title`,a.`user_id`,u.`avatar`,u.`is_vip`
FROM `ct_article` a LEFT JOIN `uc_user` u ON a.`user_id` = u.`id`
<where>
<if test="categoryId!=null and categoryId!=''">
a.`category_id` = #{categoryId}
</if>
</where>
ORDER BY a.`create_time` LIMIT #{offset},#{size};
</select>
MainListItemVo这个又是谁呢?
<resultMap id="MainListItemVo" type="net.sob.content.vo.MainListItemVo">
<result column="covers"
property="covers"
typeHandler="net.sob.content.config.CoversTypeHandler"/>
</resultMap>
这样子查询,就可以了。
okay,到这里我们的事情就处理完了,你学废了吗?
同样的思想
标签、爱好这些数据都可以使用这种方法进行处理。