今天项目经理让我们做一个Mybatis的动态sql语句配置文件
要求如下:
当参数不传则不作为查询的条件
要完成以上两个条件就不能只写简单的语句进行查询了,需要根据前端传来的数据的变化而变化。
有时前端不会传来一整条完整的数据让你去实现增删改查。
比如一个客户类有ID(自增),客户名字,客户的编码,客户的状态等等,现在传进来了一条数据,写一条数据到数据库。
但是只有客户名字,你要写到数据库直接使用
insert into custom(CUSTOM_NAME,CUSTOM_CODE,STATE)
values(#{custom_Name},#{custom_Code},#{state})
显然是不行的,因为有的字段为null,你写进去不会报错,但影响效率,不如只写
insert into custom(CUSTOM_NAME)
values(#{custom_Name})
而且对于 改 就很容易出错了,这里就不详细解释了。
那么这个时候就需要使用动态sql语句来写
而Mybatis提供了很多标签来拼接字符串,以根据实际传来的数据来写语句。
1.比如最简单的<if test="">...</if>标签,里面的test可以用于判断传来的数据是否null,为null就不拼接里面包含的内容
例:
<span style="font-size:18px;"><select id="select" parameterType="Custom" resultType="int">
SELECT * FROM CUSTOM WHERE
<if test="id != null">
id=#{id}
</if>
<if test="id != null">
and CUSTOM _NAME=#{customName}
</if>
...
</select></span>
传来的id不等于null,则拼接里面的语句
2.有时我们不想应用所有的条件, 相反我们想选择很多情况下的一种。 Java 中的 switch 和 语句相似,MyBatis 提供 <choose> 元素来表示
<span style="font-size:18px;"><choose>
<when test="id != null">
...
</when>
<when test="customName != null">
...
</when>
<otherwise>
...
</otherwise>
</choose></span>
3.在更新操作的时候还会用到 <set> 标签来表示
<span style="font-size:18px;"><update id="update" parameterType="Custom">
update custom
<set>
<if test="id != null">
ID=#{id},
</if>
<if test="customName!= null">
CUSTOM_NAME=#{customName},
</if>
<if test="customCode != null">
CUSTOM_CODE=#{customCode},
</if>
<if test="state != null">
STATE=#{state}
</if>
</set>
where ID=#{id}
</update></span>
4.在查询语句中有时用标签where来替代语句。比如在第一条的基础上可以做出修改,用标签where来替代where
<select id="select" parameterType="Custom" resultType="int">
SELECT * FROM CUSTOM
<where>
<if test="id != null">
and id=#{id}
</if>
<if test="id != null">
and CUSTOM _NAME=#{customName}
</if>
...
</where>
</select>
这样做有什么好处呢?
表面上看好像没什么好处,其实细心的同学会发现在加了<where>标签的语句中的第一条<if>里 我在id前面加了and。
要是直接用where语句,万一传来的id为空,customName不为空,那么拼接后就是where and CUSTOM_NAME=#{
customName} ,这样写出来显然是错的,所以where标签作用就来了,他可以直接忽略掉第一个and,使拼出来的
语句不会出现多一个单词的情况。当然or也适用。
5.里面还有trim标签
常见有以下:
<trim prefix="WHERE"prefixOverrides="AND |OR "> ...</trim>
prefix这里表示where元素会动态前置WHERE,然后prefixOverrides会移除前面无用的and和or
<trim prefix="SET"suffixOverrides=","> ...</trim>
prefix这里表示set元素会动态前置SET,然后suffixOverrides会移除后面无用的逗号","
6.<include>标签也是常用的,可以在语句中占个位置,引用sql语句,起到了复用的作用
比如:
insert into CUSTOM(<include refid="inserClomunsSql"></include>) values(<include refid="inserValuesSql"></include>)
<sql id="inserClomunsSql">
...
</sql>
<sql id="inserValuesSql">
...
</sql>
下面贴出我自己配置的一个mapper文件
<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xhy.mapper.CustomMapper">
<!-- useGeneratedKeys="true" 表明使用数据库自动生成的主键,
keyColumn="id" 指定Custom表中的主键列,keyProperty="id",
表明当插入记录后,会把数据库生成的主键值设置到Custom对象的id属性中,
也就是说,它指定与Custom表中的主键列对应的Custom实体类中的属性是id这个属性
-->
<insert id="add" useGeneratedKeys="true"
keyColumn="id" keyProperty="id"
parameterType="cus">
<choose>
<when test="(customName == null or "".equals(customName)) and (customCode == null or "".equals(customCode)) and (state==null or "".equals(state)) and (id==0)">
commit
</when>
<otherwise>
insert into CUSTOM(<include refid="inserClomunsSql"></include>) values(<include refid="inserValuesSql"></include>)
</otherwise>
</choose>
</insert>
<!-- 插入语句对应行判断与拼接 -->
<sql id="inserClomunsSql">
<!-- 进行判断,并且去除最后的逗号 -->
<trim suffixOverrides=",">
<!-- !"".equals(customName)表示!"".equals() -->
<if test="customName != null and !"".equals(customName)">
CUSTOM_NAME,
</if>
<if test="customCode != null and !"".equals(customCode)">
CUSTOM_CODE,
</if>
<if test="state != null and !"".equals(state)">
STATE,
</if>
<if test="id != null and !"".equals(id)">
ID,
</if>
</trim>
</sql>
<!-- 插入语句插入值的拼接 -->
<sql id="inserValuesSql">
<!-- 进行判断,并且去除最后的逗号 -->
<trim suffixOverrides=","><!-- suffixOverrides=","用于去掉拼接结果的最后一个逗号 -->
<if test="customName != null and !"".equals(customName)">
#{customName},
</if>
<if test="customCode != null and !"".equals(customCode)">
#{customCode},
</if>
<if test="state != null and !"".equals(state)">
#{state},
</if>
<if test="id != null and !"".equals(id)">
#{id},
</if>
</trim>
</sql>
<delete id="delete" parameterType="int">
<if test="id != null and id != 0">
delete from custom where id = #{id}
</if>
</delete>
<!--学生实体的属性与学生列表名的映射 -->
<resultMap id ="customResultMap"
type="cus">
<id property="id" column="id"/>
<result property="customName" column="custom_name"/>
<result property="customCode" column="custom_code"/>
<result property="state" column="state"/>
</resultMap>
<!-- resultMap就是指使用哪个映射 -->
<!-- 根据学生id查询学生对象 -->
<select id="select" parameterType="cus"
resultMap="customResultMap">
select ID,CUSTOM_NAME,CUSTOM_CODE,STATE
from custom
<!-- 标签where替代了语句where,而且功能要优于直接使用where语句 -->
<where>
<if test="id != null and id != 0">
and id=#{id}
</if>
<if test="customName != null and !"".equals(customName)">
and custom_name=#{customName}
</if>
<if test="customCode != null and !"".equals(customCode)">
and custom_code=#{customCode}
</if>
<if test="state != null and !"".equals(state)">
and state=#{state}
</if>
</where>
</select>
<!-- 查找所有的学生 -->
<select id="selectAll" parameterType="_int"
resultMap="customResultMap">
select id,custom_name,custom_code,state
from custom
</select>
<!-- 根据id修改custom表的相关信息 -->
<update id="update" parameterType="cus">
<!-- update custom set custom_name=#{customName},
custom_code=#{customCode},state=#{state}
where id=#{id} -->
<choose>
<when test="id != null and id != 0">
update custom
<set>
<if test="customName != null and !"".equals(customName)">
custom_name=#{customName},
</if>
<if test="customCode != null and !"".equals(customCode)">
custom_code=#{customCode},
</if>
<if test="state != null and !"".equals(state)">
state=#{state}
</if>
</set>
where id=#{id}
</when>
<otherwise>
commit
</otherwise>
</choose>
</update>
</mapper></span>