Mybatis之动态sql

一.动态sql的介绍

需求:查询员工信息,要求传入的参数为Emp对象,如果empName不为空,需要根据empName查询,如果empMail不为空,需要根据empMail查询,如果empGender不为空,要求根据empGender查询,要求如果deptId不为空,要求根据deptId查询。

类似于以上的需求,必须使用MyBatis的动态sql,动态sql是MyBatis强大的特性之一,能够极大的简化我们sql拼装的过程,动态sql使用标签完成动态sql,类似于我们用过的jstl,获取和其他的xml类似的语法。

二. 动态sql之if判断
 	<!-- 
		public List<Emp> selectEmpByEmp(Emp emp);
	 -->

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

现在在满足每一个if条件的情况下,正常运行,但是如果将参数中的empName设置为空,那么拼装的sql语句肯定不能够正常执行。

三. 动态sql之where查询条件

以上的程序,在指定的情况下,sql不能正常执行,要么前面多一个and,要么后面多一个and,我们有两种解决方案:

① where 1=1 …

select * from emp where 1=1
	 	<if test="empName != null and empName != ''"> <!-- test="empName != null &amp;&amp; empName != ''"  -->
	 		and emp_name = #{empName}
	 	</if>
	 	<if test="empMail != null and empMail != ''">
	 		and emp_mail = #{empMail}
	 	</if>
	 	<if test="empGender != null">
	 		and emp_gender = #{empGender}
	 	</if>
	 	<if test="deptId != null">
	 		and dept_id = #{deptId}
	 	</if>

②:MyBatis提倡的方式,就是使用where标签,将查询的判断放在where标签中

 	<!-- 
		public List<Emp> selectEmpByEmp(Emp emp);
	 -->
	<!-- 
	 <select id="selectEmpByEmp" resultType="com.wanbangee.entities.Emp">

    -->
 	select * from emp 
 	<where>
	 	<if test="empName != null and empName != ''"> <!-- test="empName != null &amp;&amp; empName != ''"  -->
	 		 emp_name = #{empName} and
	 	</if>
	 	<if test="empMail != null and empMail != ''">
	 		 emp_mail = #{empMail} and
	 	</if>
	 	<if test="empGender != null">
	 		 emp_gender = #{empGender} and
	 	</if>
	 	<if test="deptId != null">
	 		dept_id = #{deptId}
	 	</if>
 	</where>
 </select>

以上的程序依然存在问题,在deptId为null情况下,会多出一个and,导致sql报错。

四. 动态sql之trim(自定义字符串截取)

Trim标签可以很好的解决where解决不了的问题。

 	<select id="selectEmpByEmp" resultType="com.wanbangee.entities.Emp">
	 	<!-- 
    -->
 	select * from emp 
 		<!-- 
 		prefix : 添加前缀
 		suffix : 添加后缀
 		prefixOverrides : 前缀覆盖 
 			prefixOverrides="abc" 表示如果trim标签中拼凑的sql语句 以 abc 结尾,则用空串将abc覆盖
 		suffixOverrides : 后缀覆盖
 			suffixOverrides="and" 表示如果trim标签中拼凑的sql语句 最后以 and 结尾,则用空串将and覆盖
 		 -->
 		<trim prefix=" where " suffix="" prefixOverrides="abc" suffixOverrides="and" >
		 	<if test="empName != null and empName != ''"> <!-- test="empName != null &amp;&amp; empName != ''"  -->
		 		 emp_name = #{empName} and
		 	</if>
		 	<if test="empMail != null and empMail != ''">
		 		 emp_mail = #{empMail} and
		 	</if>
		 	<if test="empGender != null">
		 		 emp_gender = #{empGender} and
		 	</if>
		 	<if test="deptId != null">
		 		dept_id = #{deptId}
		 	</if>
	 	</trim>
 </select>
五. 动态sql之choose(分支选择)
<!-- 
		public List<Emp> selectEmpByEmp2(Emp emp);
	 -->
	 <select id="selectEmpByEmp2" resultType="com.wanbangee.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>
	 			<when test="deptId != null">
	 				dept_id = #{deptId}
	 			</when>
	 			<!-- <otherwise>
	 				1=1
	 			</otherwise> -->
	 		</choose>
	 	</where>
	 </select>

需求:查询员工信息,要求传入的参数为Emp对象,如果empName不为空,则根据empName查询,如果empMail不为空,则根据empMail查询,如果empGender不为空,则根据empGender查询,要求如果deptId不为空,则根据deptId查询。这个需求的要求表示查询条件只有一个,我们使用if是完成不了了,只能使用choose分支标签。

六. 动态sql之set标签与if结合进行更新

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

<!-- 
		public int updateEmp(Emp emp);
	-->
	<update id="updateEmp">
		update emp  set
		<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>

当然我们也可以使用trim标签完成

<!-- 
		public int updateEmp(Emp emp);
	-->
	<update id="updateEmp">
		update emp  
		<trim prefix=" set " suffixOverrides=",">
			<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>
		</trim>
		<where>
			<if test="empId == null"> 
			 	1 = 2
			</if>
			<if test="empId != null"> 
			 	emp_id = #{empId}
			</if>
		</where>
	</update>
七. 动态sql之foreach标签遍历集合

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

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

Mysql进行批量新增数据的两种sql语法:

# 第一种

INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id)

VALUES('AAA','aaa@163.com',1,1),

('BBB','aaa@163.com',1,1),

('CCC','aaa@163.com',1,1),

('DDD','aaa@163.com',1,1)

# 第二种

INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id)VALUES('aaa','aaa@163.com',1,1);

INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id)VALUES('bbb','aaa@163.com',1,1);

INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id)VALUES('ccc','aaa@163.com',1,1);

INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id)VALUES('ddd','aaa@163.com',1,1);

使用foreach进行批量新增:

<!-- 
		public int insertEmps(List<Emp> emps);
	 -->
	<insert id="insertEmps">
		<!--  第一种sql
		INSERT INTO emp(emp_name,emp_mail,emp_gender,dept_id) VALUES
		<foreach collection="list" separator="," item="emp">
			(#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId})
		</foreach> -->
		<!-- 第二种sql : 
			出现了问题,因为默认情况下,JDBC允许一次执行多条sql,而且使用;隔开就是多条sql,为了能让数据库一次性执行多条SQL,我们需要修改连接的参数allowMultiQueries=true
			jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf-8&useUnicode=true&allowMultiQueries=true
		-->
		<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>
	</insert>
九. Oracle环境下使用foreach进行批量插入

Oracle数据库和mysql数据库的批量新增的语法,完全不同

-- 语法1 

begin 

 INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id)VALUES(seq_2020721.nextval,'aaa','aaa@163.com',1,1);

 INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id)VALUES(seq_2020721.nextval,'bbb','aaa@163.com',1,1);

 INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id)VALUES(seq_2020721.nextval,'ccc','aaa@163.com',1,1);

 INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id)VALUES(seq_2020721.nextval,'ddd','aaa@163.com',1,1);

end ;

 
-- 语法2

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(

select 'AAA' emp_name,'aaa@qq.com' emp_mail,1 emp_gender,1 dept_id from dual

union all

select 'BBB' emp_name,'aaa@qq.com' emp_mail,1 emp_gender,1 dept_id from dual

union all

select 'CCC' emp_name,'aaa@qq.com' emp_mail,1 emp_gender,1 dept_id from dual

union all

select 'DDD' emp_name,'aaa@qq.com' emp_mail,1 emp_gender,1 dept_id from dual

)

foreach完成批量新增

<!-- 
		public int insertEmpsOracle(List<Emp> emps);
	 -->
	<insert id="insertEmpsOracle">
		<!-- 第一种语法 -->
		<!-- begin
			<foreach collection="list" item="emp">
				INSERT INTO emp_721(emp_id,emp_name,emp_mail,emp_gender,dept_id)VALUES(seq_2020721.nextval,#{emp.empName},#{emp.empMail},#{emp.empGender},#{emp.deptId});
			</foreach>
		end; -->
		<!-- 第二种语法 -->
		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>
	</insert>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值