最近,接到一个需求,要将 Excel 里的数据落到数据库里,但是由于这个 Excel 的表头不是固定的,会根据用户的需要进行修改(可能增加新的列,删除旧的列或者更新已有的列),所以设计上要能支持这样的灵活度,尽量避免代码频繁变动。于是,数据库就采用大宽表的设计,将所有相关的 Excel 列都映射成一个字段;DAO 层采用的是 mybatis,所以要实现一种基于 mybatis 的通用插入更新方案。
现实中,上层已将 Excel 解析成一个 Map 的数组,数组里的每个元素是一个 Map,表示 Excel 的每一行,该 map 的 key 是 String 类型,表示 Excel 的表头,也是数据库的相应字段名;该 map 的 value 是 Excel 的每个单元格的值。因此,具体的落地方案,就是把这个 map 落到数据库,使用动态 sql 的 foreach 对集合进行遍历,注意的是 collection 的值为 dbColumnToValueMap.keys。
对应的接口如下:
public interface ExcelDataMapper {
/**
* 根据excel解析的实体,插入到数据库。
*
* @param dbColumnToValueMap <code>Map<String, String></code> 表示excel解析的实体。
*/
int insert(@Param("dbColumnToValueMap") Map<String, Object> dbColumnToValueMap);
}
复制代码
相应的 mapper.xml 文件片段,如下:
<insert id="insert" parameterType="map">
<insert into excel_data_info
<foreach collection="dbColumnToValueMap.keys" item="key" open="(" close=")" separator=",">
${key}
</foreach>
values
<foreach collection="dbColumnToValueMap.keys" item="key" open="(" close=")" separator=",">
#{dbColumnToValueMap[${key}]}
</foreach>
</insert>
复制代码
同时,为了能支持插入和更新操作(即 upsert 操作),对上述实现进行更新,使用了 mysql 的 on duplicate key update 的语法,接口和 mapper.xml 的文件也进行了调整。
对应的接口如下:
public interface ExcelDataMapper {
/**
* 根据excel解析的实体,插入或更新到数据库。
*
* @param dbColumnToValueMap <code>Map<String, String></code> 表示excel解析的实体。
*/
int upsert(@Param("dbColumnToValueMap") Map<String, Object> dbColumnToValueMap);
}
复制代码
相应的 mapper.xml 文件片段,如下:
<insert id="upsert" parameterType="map">
insert into excel_data_info
<foreach collection="dbColumnToValueMap.keys" item="key" open="(" close=")" separator=",">
${key}
</foreach>
values
<foreach collection="dbColumnToValueMap.keys" item="key" open="(" close=")" separator=",">
#{dbColumnToValueMap[${key}]}
</foreach>
on duplicate key update
<foreach collection="dbColumnToValueMap.keys" item="key" separator="," >
<if test=" key != 'id' ">
${key} = #{dbColumnToValueMap[${key}]}
</if>
</foreach>
</insert>
复制代码
通过上述方案,实现了一种 mybatis 的通用插入更新方案。
参考:
1.https://mybatis.org/mybatis-3/zh/dynamic-sql.html
2.https://mybatis.org/mybatis-3/zh/dynamic-sql.html
评论