Context
现在有8个表,都有相同的两列。
需求就是选择 表&id,修改对应行的列值
8个表诶,两个操作就要写16个sql,还要判断枚举值选择不同的Dao,返回不同的实体…
啊,真的是太麻烦了。。要写这么多重复的代码,那一定会有更好的方法
show time~
- select
查操作要简单很多,参数是表名和id
我们可以用${}传入表名,statementType="STATEMENT"在预编译前把SQL拼接好
<select id="selectTaskTable" resultMap="rasSqlAssistMap" statementType="STATEMENT">
select id, columnName1, columnName2 from ${tableName} where id = ${id}
</select>
踩坑1一开始我写的是"where id = #{id}",但编译出来是"where id = "
如果设置了非预编译,就不能再使用#{}了,都要统一用${}
因为#{}的变量替换是在预编译阶段,在SQL解析阶段是显示不出来的
- update
更新操作就麻烦很多了,因为更新的列不确定(两个列不一定都更新)
踩坑2
我本来想传入Map然后用判空,还是上面的坑,这些动态sql在解析阶段是解析不出来的,编译完set中间一片空白。。
<update id="updateByTableName" parameterType="String" statementType="STATEMENT">
update ${tableName}
<set>
<if test="columnName1 != null and columnName1 != ''">
columnName1 = ${property1},
</if>
<if test="columnName2 != null and columnName2 != ''">
columnName2 = ${property2},
</if>
</set>
where id = ${id}
-->
</update>
但是不要放弃,懒还是要偷的
那我们在代码里拼接sql吧
StringBuilder sql = new StringBuilder();
sql.append("update "+ tableName +" ");
if (columnName1 != null && columnName2 != null){
sql.append("set columnName1 = \"");
sql.append(columnValue1);
sql.append("\"");
sql.append(", columnName2 = \"");
sql.append(columnValue2);
sql.append("\"");
sql.append(" where id = \"");
sql.append(id);
sql.append("\"");
}
mapper:
<update id="updateByTableName" parameterType="String">
${value}
</update>
把sql.toString()传进去就好啦~
拼接完是这样的:
"update tableName set columnName1 = “19”, columnName2 = “1” where id = “133"”
完美解决问题~
#与$的区别
比如
select id, columnName1, columnName2 from tableName where id = #{id}
//编译完
select id, columnName1, columnName2 from tableName where id = ?
- #{}
被解析为一个参数占位符?
在预编译阶段向占位符中注入值
将传入的参数当成字符串,会给参数加上"",预编译阶段自动进行Java类型和jdbc类型转换
select id, columnName1, columnName2 from tableName where id = ${id}
//在预编译前完成
select id, columnName1, columnName2 from tableName where id = 133
- ${}
会在预编译前拼接好sql
不会加上"",所以有sql注入的危险,使用要慎重
不听话的实习僧日常:
懒是促进发展的源泉