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,如下所示:

  1. <select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
  2. select *from tbl_employee
  3. where
  4. <!--
  5. test:判断表达式(OGNL)
  6. OGNL参照PPT或者官方文档。
  7. c:if test
  8. 从参数中取值进行判断
  9. 遇见特殊符号,应该去写转义字符:参考W3CSchool>>HTML>>ISO8859
  10.  
  11. -->
  12. <if test="id != null">
  13. id = #{id}
  14. </if>
  15. <if test="userName != null && userName !=''">
  16. and user_name = #{userName}
  17. </if>
  18. <if test="email != null and email.trim() != """>
  19. and email = #{email}
  20. </if>
  21. <!-- ognl会进行字符串和数字的转换判断;"0"==0,"1"==1 -->
  22. <if test="gender == 0 or gender == 1">
  23. and gender = #{gender}
  24. </if>
  25. </select>

   4).测试代码:

  1. @Test
  2. public void testGetEmployee(){
  3. EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
  4. Employee employee = new Employee();
  5. employee.setId(1);
  6. employee.setUserName("张三丰");
  7. employee.setEmail("sunwukong@163.com");
  8. employee.setGender(1);
  9. List<Employee> list = mapper.getEmployeeByConditionIf(employee);
  10. System.out.println(list);
  11. }

  

但是仔细来说,上面的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标签:可以自定义字符串的截取规则

  1. <select id="getEmployeeByConditionIf" resultType="com.neuedu.entity.Employee">
  2. select *from tbl_employee
  3. <!--
  4. 后面多出的and或者or where标签不能够解决
  5. prefix="":前缀:trim标签体重是整个字符串拼串后的结果。
  6. prefix给拼串后的整个字符串加一个前缀
  7. prefixOverrides="":
  8. 前缀覆盖:去掉整个字符串前面多余的字符
  9. suffix="":后缀
  10. suffix给拼串后的整个字符串加一个后缀
  11. suffixOverrides="":
  12. 后缀覆盖:去掉整个字符串后面多余的字符
  13. -->
  14. <trim prefix="where" suffixOverrides="and">
  15. <if test="id != null">
  16. id = #{id} and
  17. </if>
  18. <if test="userName != null && userName !=''">
  19. user_name = #{userName} and
  20. </if>
  21. <if test="email != null and email.trim() != """>
  22. email = #{email} and
  23. </if>
  24. <!-- ognl会进行字符串和数字的转换判断;"0"==0,"1"==1 -->
  25. <if test="gender==0 or gender==1">
  26. gender = #{gender}
  27. </if>
  28. </trim>
  29. </select>

  3.choose标签:分支选择,类似于Java中的带了break的switch...case

choose (when, otherwise):如果带了id,就用id查,如果带了userName就用userName查,只会进入其中一个!

案例演示:
     1>.在EmployeeMapper接口中添加一个方法:
            public List<Employee> getEmployeeByConditionChoose(Employee employee);
        2>.sql映射文件

  1. <!-- public List<Employee> getEmployeeByConditionChoose(Employee employee); -->
  2. <select id="getEmployeeByConditionChoose" resultType="com.neuedu.entity.Employee">
  3. select *from tbl_employee
  4. <where>
  5. <!-- 如果带了id,就用id查,如果带了userName就用userName查,只会进入其中一个! -->
  6. <choose>
  7. <when test="id != null">
  8. id = #{id}
  9. </when>
  10. <when test="userName != null">
  11. user_name like #{userName}
  12. </when>
  13. <when test="email != null">
  14. email = #{email}
  15. </when>
  16. <otherwise>
  17. 1=1
  18. </otherwise>
  19. </choose>
  20. </where>
  21. </select>

  

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

1).在EmployeeMapper中添加一个更新的方法,如下所示:
              public void updateEmp(Employee employee);
         2)在sql映射文件中,填写相应的sql语句,如下所示【set标签可以将字段后面的逗号去掉】:

  1. <update id="updateEmp">
  2. update tbl_employee
  3. <set>
  4. <if test="userName != null">
  5. user_name = #{userName},
  6. </if>
  7. <if test="email != null">
  8. email = #{email},
  9. </if>
  10. <if test="gender != null">
  11. gender = #{gender},
  12. </if>
  13. </set>
  14. where id = #{id}
  15. </update>

  测试类代码为:

  1. @Test
  2. public void testGetEmployee(){
  3. EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
  4. Employee employee = new Employee();
  5. employee.setId(1);
  6. employee.setUserName("哈哈");
  7. employee.setEmail("sunwukong@163.com");
  8. employee.setGender(1);
  9. mapper.updateEmp(employee);
  10. }
  11.  
  12. //当然上面的set标签我们也可以使用trim标签来代替,如下所示:
  13. <update id="updateEmp">
  14. update tbl_employee
  15. <trim prefix="set" suffixOverrides=",">
  16. <if test="userName != null">
  17. user_name = #{userName},
  18. </if>
  19. <if test="email != null">
  20. email = #{email},
  21. </if>
  22. <if test="gender != null">
  23. gender = #{gender},
  24. </if>
  25. </trim>
  26. where id = #{id}
  27. </update>

  5.foreach:遍历元素

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

案例演示:
         1>.在EmployeeMapper接口中加入一个方法,如下所示:
            public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);
         2>.在MyBatis的sql映射文件中写相应的代码:

  1. <!-- public List<Employee> getEmpsByConditionForeach(List<Integer> ids); -->
  2. <select id="getEmpsByConditionForeach" resultType="com.neuedu.entity.Employee">
  3. select * from tbl_employee where id in
  4. <!--
  5. collection:指定要遍历的集合
  6. item:将当前遍历出的元素赋值给指定的变量
  7. separator:每个元素之间的分隔符
  8. open:遍历出所有记过拼接一个开始的字符
  9. close:遍历出所有结果拼接一个结束的字符
  10. -->
  11. <foreach collection="ids" open="(" close=")" separator="," item="id">
  12. #{id}
  13. </foreach>
  14. </select>

     3.>测试类代码为:

  1. @Test
  2. public void testGetEmployee(){
  3. EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
  4. List<Integer> asList = Arrays.asList(1,2,3,4);
  5. List<Employee> emps = mapper.getEmpsByConditionForeach(asList);
  6. for (Employee employee : emps) {
  7. System.out.println(employee);
  8. }
  9. }

  

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", "allen@163.com", new Department(1)));
emps.add(new Employee(0, 0, "tom", "tom@163.com", new Department(2)));
emps.add(new Employee(0, 1, "mux", "mux@163.com", new Department(1)));
mapper.addEmps(emps);
}

动态拼接SQL语句的更多相关文章

  1. java动态拼接sql语句并且执行时给sql语句的参数赋值

    问题 在这里举一个例子,比如我要做一个多条件模糊查询,用户输入的时候有可能输入一个条件,也有可能输入两个条件,这时执行查询的sql语句就不确定了,但可以用动态拼接sql语句来解决这个问题. 解决方法 ...

  2. 动态拼接SQL 语句

    public T Get<T>(int id) { Type type = typeof(T); string columnStrings = string.Join(",&qu ...

  3. SQL 动态拼接SQL 语句

    USE [PMS_UnifiedDB_15] GO /****** Object: StoredProcedure [dbo].[SP_GetLogInfo] Script Date: 2/11/20 ...

  4. 查询拼接SQL语句,多条件模糊查询

    多条件查询,使用StringBuilder拼接SQL语句,效果如下: 当点击按钮时代码如下: private void button1_Click(object sender, EventArgs e ...

  5. sp_executesql动态执行sql语句并将结果赋值给一变量

    需求场景: 需动态拼接sql语句进行执行,并将执行的结果赋值给一指定变量. 样例代码如下: SELECT @tableName = TAB_NAME FROM dbo.NMR_BLYWBDY WHER ...

  6. 动态执行SQL语句

    在实际制作过程中,需要动态的拼接SQL语句然后执行.具体代码如下: declare @columnName varchar(20),@tempName varchar(20) select @temp ...

  7. 使用exec和sp_executesql动态执行SQL语句(转载)

    当需要根据外部输入的参数来决定要执行的SQL语句时,常常需要动态来构造SQL查询语句,个人觉得用得比较多的地方就是分页存储过程和执行搜索查询的SQL语句.一个比较通用的分页存储过程,可能需要传入表名, ...

  8. 动态执行SQL语句,接收返回值

    一.exec和sp_executesql介绍 当需要根据外部输入的参数来决定要执行的SQL语句时,常常需要动态来构造SQL查询语句.比如,一个比较通用的分页存储过程,可能需要传入表名,字段,过滤条件, ...

  9. mysql 存储过程动态执行sql语句

    之前经常在程序中拼接sql语句,其实我们也可以在存储过程中拼接sql 语句,动态的执行~~ 代码如下: DROP PROCEDURE IF EXISTS SearchByDoctor;CREATE P ...

随机推荐

  1. settings.xml样例文件

    localRepository G:\program-my\maven-responsery true --> false --> com.your.plugins --> prox ...

  2. php面试题分享

    1.nginx使用哪种网络协议? nginx是应用层 我觉得从下往上的话 传输层用的是tcp/ip 应用层用的是http fastcgi负责调度进程 2. <? echo 'hello tush ...

  3. 用CSS控制图片大小显示的方法

    图片自动适应大小是一个非常常用的功能,在进行制作的时候为了防止图片撑开容器而对图片的尺寸进行必要的控制,我们可不可以用CSS控制图片使它自适应大小呢? 可以通过按比例缩小或者放大到某尺寸(自己指定), ...

  4. CentOS 6.2安装nagios

    nagios分为监控机和被监控机两类机器      监控主机:gserver150(192.168.111.150) 被监控主机:gserver151(192.168.111.151)   一.  监 ...

  5. 零基础逆向工程25_C++_02_类的成员权限_虚函数_模板

    1 类的成员权限 1.1 小结: 1.对外提供的函数或者变量,发布成public的 但不能随意改动. 2.可能会变动的函数或者变量,定义成private的 这样编译器会在使用的时候做检测. 3.只有结 ...

  6. [转]c语言宏定义#define的理解与资料整理

    原文地址:http://www.cnblogs.com/haore147/p/3646934.html 1. 利用define来定义 数值宏常量 #define 宏定义是个演技非常高超的替身演员,但也 ...

  7. 菜鸟 学注册机编写之 “MD5”

    测试环境  系统: xp sp3 调试器 :od 1.10 sc_office_2003_pro 高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激! 一:定位关键CALL 1. 因 ...

  8. sql优化经典例子

    场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course( c_id int PRIMARY KEY, name varchar(10) ) 数据10 ...

  9. spring中用xml配置构造注入的心得

    spring中用xml配置构造注入时,如果 <constructor-arg> 属性都是 ref ,则不用理会参数顺序 <constructor-arg ref="kill ...

  10. 关于docker容器内核参数修改问题

    以下内容截取自docker官方文档 地址:https://docs.docker.com/edge/engine/reference/commandline/run/#configure-namesp ...