动态 SQL

动态 SQL

我们都知道,有时候需要根据业务逻辑去拼装 SQL 语句是一件很麻烦的事,因为除了拼装以为,还需要判断最后是否有多余的 ,and,or 等导致语法错误的字符,而且得保证空格才不会导致 SQL 语句挤到一起。利用 MyBatis 的动态 SQL 就能摆脱苦恼。

if

如果传入的参数是一个实体类,并且当实体类的某个属性不为 null 的时候就加入 where 条件。

 	<select id="selectEmpByEmp" resultType="com.nhky.entities.Emp">
	 	select * from emp where 
	 	<if test="empName != null and empName != ''">
	 		emp_name = #{empName}
	 	</if>
	 	<if test="empMail != null and empMail != ''">
	 		and emp_mail = #{empMail}
	 	</if>
	 	<if test="deptId != null">
	 		and dept_id = #{deptId}
	 	</if>
	 </select>

上面的代码的意思是,如果 empName 不为 null 或空串,就设定 emp_name 的查询条件为指定的值。其他 if 标签也是类似的意思。

where

 	<select id="selectEmpByEmp" resultType="com.nhky.entities.Emp">
	 
	 	select * from emp 
        <where>
            <if test="empName != null and empName != ''">
                emp_name = #{empName}
            </if>
            <if test="empMail != null and empMail != ''">
                and emp_mail = #{empMail}
            </if>
            <if test="deptId != null">
                and dept_id = #{deptId}
            </if>
        </where>
	 </select>

where 标签就代替了上面例子我们 sql 的 where 关键字,并且在有些时候,比较智能。例如我们的 where 标签没有内容,那么 where 的关键字是不会添加进去导致语句出错,省去了我们的判断。

trim

trim 用于字符串截取,上面的程序有问题,如果说,我们的 empName 为 null,而后面 empMail 不为 null,那么 sql 语句就会变成这样

  • select * from emp and emp_mail = ?

sql 语句就会报错。那么如何解决?采用 trim 标签字符串截取

	<select id="selectEmpByEmp" resultType="com.nhky.entities.Emp">
	 
	 	select * from emp 
        <where>
            <trim prefix="" suffix="" prefixOverrides="and" suffixOverrides="">
                <if test="empName != null and empName != ''">
                    emp_name = #{empName}
                </if>
                <if test="empMail != null and empMail != ''">
                    and emp_mail = #{empMail}
                </if>
                <if test="deptId != null">
                    and dept_id = #{deptId}
                </if>
            </trim>
        </where>
	 </select>
  • prefix : 添加前缀
  • suffix : 添加后缀
  • prefixOverrides : 前缀覆盖
    • prefixOverrides=“abc” 表示如果 trim 标签中拼凑的 sql 语句以 abc 开头,则用空串将 abc 覆盖
  • suffixOverrides : 后缀覆盖
    • suffixOverrides=“and” 表示如果 trim 标签中拼凑的 sql 语句 最后以 and 结尾,则用空串将 and 覆盖

choose

假如传入的参数还是一个实体类 emp,choose 标签用于分支选择,类似于 if-else if-else if - else… 语句。

	 <select id="selectEmpByEmp2" resultType="com.nhky.entities.Emp">
	 	select * from emp 
	 	<where>
	 		<choose>
	 			<when test="empName != null and empName != ''">
	 				emp_name = #{empName}
	 			</when>
	 			<when test="empMail != null and empMail != ''">
	 				emp_mail = #{empMail}
	 			</when>
	 			<when test="empGender != null">
	 				emp_gender = #{empGender}
	 			</when>
	 			<otherwise>
	 				1=1
	 			</otherwise>
	 		</choose>
	 	</where>
	 </select>

查询员工信息,要求传入的参数为 Emp 对象,如果 empName 不为空,则根据empName 查询,并且其他条件不再判断。如果empMail不为空,则根据 empMail 查询,其他条件不再判断,以此类推。这个需求的要求表示查询条件只有一个,我们使用 if 是完成不了了,只能使用choose分支标签。

otherwise 标签用于在其他 when 标签不能的时候,垫底的。整个 choose 类似于 if-else if - else if- else 一样。

set

Set 标签用于修改。根据emp_id 修改emp数据,入参为Emp对象,对象中如果empName不为空,empName则需要修改,如果empMail不为空,则empMail需要修改…

<update id="updateEmp">
		update emp 
		<set>
			<if test="empName != null and empName != ''"> 
			 		 emp_name = #{empName} ,
			</if>
		 	<if test="empMail != null and empMail != ''">
			 		 emp_mail = #{empMail} ,
			</if>
			<if test="empGender != null">
			 		 emp_gender = #{empGender} ,
			</if>
			<if test="deptId != null">
			 		dept_id = #{deptId}
			</if>
		</set>
		<where>
			<if test="empId == null"> 
			 	1 = 2
			</if>
			<if test="empId != null"> 
			 	emp_id = #{empId}
			</if>
		</where>
	</update>

并且 set 标签很智能,在上面的程序中,如果 deptId 为 null,那么会多余一个 ,但是 set 标签会自动去除,和 trim 很像(这里也可以用 trim 实现)。

foreach

Foreach 标签用来遍历集合的,如何使用呢?范例:传入一个 Integer 类型的 List 集合,要求 emp_id in (集合中的数据),这个时候我们可以使用 foreach 标签去循环遍历 list 集合。

	 <select id="selectEmpByEmpIds" resultType="com.wanbangee.entities.Emp">
	 	select * from emp where emp_id in
	 	
	 	<foreach collection="ids" open="(" close=")" separator="," item="id">
	 		#{id}
	 	</foreach>
	 </select>
  • collection : 表示要遍历的集合,
    • 如果传入的参数是List类型,那么可以使用list或者collection,如果传入是Set集合,只能使用collection
    • 实际上我们在接口的方法中使用@Param指定collection属性使用的值 ,指定之后,能使用指定的内容和param1…
    • open : 前缀添加
    • close:后缀添加
    • separator : 每次遍历的分割符
    • index:遍历次数
    • item : 每次遍历的数据赋值的变量

foreach 批量新增

第一种方法

	<insert id="insertEmp" >
		insert into emp values 
			<foreach collection="list" open="" close="" separator="," item="emp">
				(null,#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId})
			</foreach>
	</insert>

第二种方法

	<insert id="insertEmp2" >
			<foreach collection="list" open="" close="" separator="," item="emp">
				insert into emp values (null,#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId})
			</foreach>
	</insert>	

内置参数(多数据库支持)

我们在开发的时候,可以在insert,update,delete和select标签中,指定databaseid属性,表示不同的数据执行的不同的sql,实际上sql映射文件中还存在另外一个隐式参数,_databaseId,我们可以通过此隐式参数来执行不同的SQL。

	<insert id="insertEmpsOracle" >
		<if test="_databaseId=='oracle'">
			INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id) select seq_2020721.nextval,emp_name,emp_mail,emp_gender,dept_id from
			<foreach collection="list" close=")" open="(" separator=" union all " item="emp">
				select #{emp.empName} emp_name,#{emp.empMail} emp_mail,#{emp.empGender} emp_gender,#{emp.deptId} dept_id from dual
			</foreach>
		</if>
		<if test="_databaseId == 'mysql'">
			<foreach collection="list" separator=";" item="emp">
				INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id) VALUES (#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId})
			</foreach>
		</if>
</insert>

抽取重用 sql 片段

有些 sql 是重复的,那么我们可以抽取出来,使用sql标签定义,在使用的时候 include引用抽取的 sql 片段:

	<!-- 抽取重用的sql片段 -->
	<sql id="emp_column">
		emp_id,emp_name,emp_mail,emp_gender,dept_id
	</sql>

使用抽取的 sql 片段,用 include 标签 <include refid="emp_column"></include>

	<insert id="insertEmpsOracle" >
	<if test="_databaseId=='oracle'">
			INSERT INTO emp_721(<include refid="emp_column"></include>) select seq_2020721.nextval,<include refid="emp_column"></include> from
			<foreach collection="list" close=")" open="(" separator=" union all " item="emp">
				select #{emp.empName} emp_name,#{emp.empMail} emp_mail,#{emp.empGender} emp_gender,#{emp.deptId} dept_id from dual
			</foreach>
		</if>
		<if test="_databaseId == 'mysql'">
			<foreach collection="list" separator=";" item="emp">
				INSERT INTO emp(<include refid="emp_column"></include>) VALUES (#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId})
			</foreach>
		</if>
	</insert>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值