动态SQL (if , choose (when, otherwise) , trim (where, set) , set , foreach)

为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句。
最常用的就是:where和if标签

1.参考官方文档
	? if:字符判断
	? choose (when, otherwise):分支选择
	? trim (where, set):字符串截取;其中where标签封装查询条件,set标签封装修改条件
	? foreach

2.if案例:
	1)在EmployeeMapper接口中添加一个方法:
		//携带了哪个字段,查询条件就带上哪个字段的值
		public List<Employee> getEmployeeByConditionIf(Employee employee);

    2).如果要写下列的SQL语句,只要是不为空,就作为查询条件,如下所示,这样写实际上是有问题的,所以我们要写成动态SQL语句:
		<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
			select *from tbl_employee where id = #{id} and user_name = #{userName} and email = #{email} and gender = #{gender}
		</select>

	3)用if标签改写为动态SQL,如下所示:
			<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
				select *from tbl_employee
				where
				 <!--
					test:判断表达式(OGNL)
					OGNL参照PPT或者官方文档。
						c:if test
					从参数中取值进行判断
					遇见特殊符号,应该去写转义字符:参考W3CSchool>>HTML>>ISO8859

				  -->
				  <if test="id != null">
					id = #{id}
				  </if>
				  <if test="userName != null && userName !=‘‘">
					and user_name = #{userName}
				  </if>
				  <if test="email != null and email.trim() != """>
					and email = #{email}
				  </if>
				  <!-- ognl会进行字符串和数字的转换判断;"0"==0,"1"==1 -->
				  <if test="gender == 0 or gender == 1">
					and gender = #{gender}
				  </if>
			</select>

    4).测试代码:
		@Test
		public void testGetEmployee(){
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee employee = new Employee();
			employee.setId(1);
			employee.setUserName("张三丰");
			employee.setEmail("[email protected]");
			employee.setGender(1);
			 List<Employee> list = mapper.getEmployeeByConditionIf(employee);
			System.out.println(list);
		}

  #测试结果没问题

  但是仔细来说,上面的sql语句是有问题的,当我们不给动态sql语句传递id值的时候,sql语句的拼装就会有问题!
  解决办法:
    1.给where后面加上1=1,以后的条件都可以使用and xxx了
	2.mybatis可以使用where标签来将所有的查询条件包括在内。mybatis就会将where标签中拼装的sql,
	  多出来的and或者or去掉!//需要注意:where标签只会去掉第一个多出来的and或者or

	3.也就是说使用where标签有时候还是不能解决问题的,那怎么办呢?我们这里可以使用trim标签!

2.trim标签:可以自定义字符串的截取规则

			<select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
				select *from tbl_employee
				<!--
					后面多出的and或者or where标签不能够解决
				   prefix="":前缀:trim标签体重是整个字符串拼串后的结果。
							 prefix给拼串后的整个字符串加一个前缀
				   prefixOverrides="":
							前缀覆盖:去掉整个字符串前面多余的字符
				   suffix="":后缀
					 suffix给拼串后的整个字符串加一个后缀
				   suffixOverrides="":
						 后缀覆盖:去掉整个字符串后面多余的字符
				 -->
				<trim prefix="where" suffixOverrides="and">
				  <if test="id != null">
					id = #{id} and
				  </if>
				  <if test="userName != null && userName !=‘‘">
					user_name = #{userName} and
				  </if>
				  <if test="email != null and email.trim() != """>
					email = #{email} and
				  </if>
				  <!-- ognl会进行字符串和数字的转换判断;"0"==0,"1"==1 -->
				  <if test="gender==0 or gender==1">
				   gender = #{gender}
				  </if>
				</trim>
			</select>

3.choose标签:分支选择,类似于Java中的带了break的switch...case
	choose (when, otherwise):如果带了id,就用id查,如果带了userName就用userName查,只会进入其中一个!

	案例演示:
	   1.在EmployeeMapper接口中添加一个方法:
			public List<Employee> getEmployeeByConditionChoose(Employee employee);
	   2.sql映射文件
			<!-- public List<Employee> getEmployeeByConditionChoose(Employee employee); -->
			<select id="getEmployeeByConditionChoose" resultType="com.neuedu.entity.Employee">
				select *from tbl_employee
				<where>
					<!-- 如果带了id,就用id查,如果带了userName就用userName查,只会进入其中一个! -->
					<choose>
						<when test="id != null">
							id = #{id}
						</when>
						<when test="userName != null">
							user_name like #{userName}
						</when>
						<when test="email != null">
						   email = #{email}
						</when>
						<otherwise>
							1=1
						</otherwise>
					</choose>
				</where>
			</select>

4.trim 中的set标签(where, set):字符串截取;其中where标签封装查询条件,set标签封装修改条件
	set元素会动态前置set关键字,同时也会消除无关的逗号。

    1).在EmployeeMapper中添加一个更新的方法,如下所示:
		public void updateEmp(Employee employee);
	2)在sql映射文件中,填写相应的sql语句,如下所示【set标签可以将字段后面的逗号去掉】:
		<update id="updateEmp">
			update tbl_employee
			<set>
				<if test="userName != null">
					user_name = #{userName},
				</if>
				<if test="email != null">
					email = #{email},
				</if>
				<if test="gender != null">
					gender = #{gender},
				</if>
			</set>
			where id = #{id}
		</update>

	测试类代码为:
		@Test
		public void testGetEmployee(){
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee employee = new Employee();
			employee.setId(1);
			employee.setUserName("哈哈");
			employee.setEmail("[email protected]");
			employee.setGender(1);
			mapper.updateEmp(employee);
		}

	//当然上面的set标签我们也可以使用trim标签来代替,如下所示:
			<update id="updateEmp">
				update tbl_employee
				<trim prefix="set" suffixOverrides=",">
					<if test="userName != null">
						user_name = #{userName},
					</if>
					<if test="email != null">
						email = #{email},
					</if>
					<if test="gender != null">
						gender = #{gender},
					</if>
				</trim>
				where id = #{id}
			</update>

5.foreach:遍历元素
	动态SQL的另一个常用的操作是需要对一个集合进行遍历,通常在构建in条件语句的时候!
	foreach元素允许指定一个集合,声明集合项和索引变量,并可以指定开闭匹配的字符串以及在迭代之间放置分隔符。

	案例演示:
	 1.在EmployeeMapper接口中加入一个方法,如下所示:
		   public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);
	 2.在MyBatis的sql映射文件中写相应的代码:
			<!-- public List<Employee> getEmpsByConditionForeach(List<Integer> ids); -->
			<select id="getEmpsByConditionForeach" resultType="com.neuedu.entity.Employee">
				select * from  tbl_employee where id in
				<!--
					collection:指定要遍历的集合
					item:将当前遍历出的元素赋值给指定的变量
					separator:每个元素之间的分隔符
					open:遍历出所有记过拼接一个开始的字符
					close:遍历出所有结果拼接一个结束的字符
				 -->
				<foreach collection="ids" open="(" close=")" separator="," item="id">
					#{id}
				</foreach>
			</select>

     3.测试类代码为:
			@Test
			public void testGetEmployee(){
				EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
				List<Integer> asList = Arrays.asList(1,2,3,4);
				List<Employee> emps = mapper.getEmpsByConditionForeach(asList);
				for (Employee employee : emps) {
					System.out.println(employee);
				}
			}

   foreach标签还可以用于批量保存数据,如下所示:

     1.在EmployeeMapper接口类中添加批量插入的方法:
			public void addEmps(@Param("emps") List<Employee> emps);

     2.在EmployeeMapper.xml的sql映射文件中添加响应的语句:

			<!-- public void addEmps(@Param("emps") List<Employee> emps); -->
			<!-- MySQL下批量保存:可以foreach遍历,mysql支持values(),(),()语法 -->
			<insert id="addEmps">
				INSERT INTO tbl_employee(user_name,gender,email,d_id) VALUES
				<foreach collection="emps" item="emp" separator=",">
					(#{emp.userName},#{emp.gender},#{emp.email},#{emp.depart.id})
				</foreach>
			</insert>
	 3.测试代码:
			@Test
			public void testGetEmployee(){
				EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
				List<Employee> emps = new ArrayList<Employee>();
				emps.add(new Employee(0, 1, "allen", "[email protected]", new Department(1)));
				emps.add(new Employee(0, 0, "tom", "[email protected]", new Department(2)));
				emps.add(new Employee(0, 1, "mux", "[email protected]", new Department(1)));
				mapper.addEmps(emps);
			}

  

时间: 2024-08-09 06:15:53

动态SQL (if , choose (when, otherwise) , trim (where, set) , set , foreach)的相关文章

[刘阳Java]_MyBatis_动态SQL标签用法_第7讲

1.MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. 2.MyBatis中用于实现动态SQL的元素主要有 if choose(when,otherwise) trim where set foreach 可以看出MyBatis的动态SQL的标签元素和接近JSP中的JSTL语法,下面我就分别详细的介绍一下 3.动态SQL中if的用法 <?xml version="1.0" encoding="UTF-8" ?&g

MyBatis使用动态SQL标签的小陷阱

现在MyBatis越来越受大家的喜爱了,它的优势大家都知道,我就不多说了,直接说重点. MyBatis中提供动态SQL功能,我们可以使用<if><when><where><otherwise><foreach>等等,这样我们就可以写出根据条件生成的动态SQL了,但是,在这中间,我们经常用到的<if>标签有一个小误区,一不小心就会掉下去,下面先举个正常的例子: <select id="findActiveBlogWith

MyBatis动态SQL中trim标签的使用

My Batis 官方文档 对 动态SQL中使用trim标签的场景及效果介绍比较少. 事实上trim标签有点类似于replace效果. trim 属性 prefix:前缀覆盖并增加其内容 suffix:后缀覆盖并增加其内容 prefixOverrides:前缀判断的条件 suffixOverrides:后缀判断的条件 比如: Java代码   select b.* from sys_menu b where 1 = 1 <trim suffix="WHERE" suffixOve

MyBatis动态SQL之一使用 if 标签和 choose标签

bootstrap react https://segmentfault.com/a/1190000010383464 xml 中 < 转义 to thi tha <if test="pricehigh!=null"> and price < #{pricehigh,jdbcType=INTEGER} </if> MyBatis动态SQL之一使用 if 标签和 choose标签 <select id="getItems" p

MyBatis4:动态SQL

什么是动态SQL MyBatis的一个强大特性之一通常是它的动态SQL能力.如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的省略逗号,动态SQL可以彻底处理这种痛苦. 通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中. 动态SQL元素和使用JSTL或其它相似的基于XML的文本处理器相似,在MyBatis之前的版本中,有很多元素需

MyBatis动态SQL小结

p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; font-size: 10.5pt; font-family: 等线 } .MsoChpDefault { font-family: 等线 } div.WordSection1 { } ol { margin-bottom: 0cm } ul { margin-bottom: 0cm } Mybati

笔记:MyBatis 动态SQL

有时候,静态的SQL语句并不能满足应用程序的需求.我们可以根据一些条件,来动态地构建SQL语句.例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作.在实现这种类型的搜索功能,我们可能需要根据这些条件来构建动态的SQL语句.如果用户提供了任何输入条件,我们需要将那个条件 添加到SQL语句的WHERE子句中. MyBatis通过使用<if>,<choose>,<where>,<foreach>,<

MyBatis 动态sql详解

MyBatis的动态sql语句 1.if 条件 2.choose , when 和 otherwise条件 3.where 条件 where条件:1.自动加上where.2.如果where子句以and或者or开头,则自动删除第一个and或者or..所以我们不需要自己加where 4.trim 条件 trim条件和where条件类似但是功能更强大:不仅可以替换掉子句开头的and或者or,还提供了加前缀和后缀的功能. 5.forEach循环 6.set 条件 set条件:自动加上set,自动去除最后

MyBatis的动态SQL详解

MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力.如果你有使用 JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号.动态 SQL 可以彻底处理这种痛苦. 通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种