mybatis之动态SQL

Posted 每天进步一点点,好记性不如烂笔头

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis之动态SQL相关的知识,希望对你有一定的参考价值。

mybatis作为当今最流行的持久层框架,在开发中也经常使用到,今天这篇博文主要讲的是动态SQL,也是我们日常开发中非常常用的技术。

创建两个实体类,员工类和部门类:

 1 package com.atguigu.mybatis.bean;
 2 
 3 import org.apache.ibatis.type.Alias;
 4 
 5 @Alias("emp")
 6 public class Employee {
 7     
 8     private Integer id;
 9     private String lastName;
10     private String email;
11     private String gender;
12     private Department dept;
13     
14     public Employee() {
15         super();
16     }
17     
18     
19     
20     public Employee(Integer id, String lastName, String email, String gender,
21             Department dept) {
22         super();
23         this.id = id;
24         this.lastName = lastName;
25         this.email = email;
26         this.gender = gender;
27         this.dept = dept;
28     }
29 
30 
31 
32     public Employee(Integer id, String lastName, String email, String gender) {
33         super();
34         this.id = id;
35         this.lastName = lastName;
36         this.email = email;
37         this.gender = gender;
38     }
39     
40     
41     
42 
43     public Department getDept() {
44         return dept;
45     }
46 
47     public void setDept(Department dept) {
48         this.dept = dept;
49     }
50 
51     public Integer getId() {
52         return id;
53     }
54     public void setId(Integer id) {
55         this.id = id;
56     }
57     public String getLastName() {
58         return lastName;
59     }
60     public void setLastName(String lastName) {
61         this.lastName = lastName;
62     }
63     public String getEmail() {
64         return email;
65     }
66     public void setEmail(String email) {
67         this.email = email;
68     }
69     public String getGender() {
70         return gender;
71     }
72     public void setGender(String gender) {
73         this.gender = gender;
74     }
75     @Override
76     public String toString() {
77         return "Employee [id=" + id + ", lastName=" + lastName + ", email="
78                 + email + ", gender=" + gender + "]";
79     }
80     
81     
82 
83 }
 1 package com.atguigu.mybatis.bean;
 2 
 3 import java.util.List;
 4 
 5 public class Department {
 6     
 7     private Integer id;
 8     private String departmentName;
 9     private List<Employee> emps;
10     
11     public Department(Integer id) {
12         super();
13         this.id = id;
14     }
15     public Department() {
16         super();
17         // TODO Auto-generated constructor stub
18     }
19     public List<Employee> getEmps() {
20         return emps;
21     }
22     public void setEmps(List<Employee> emps) {
23         this.emps = emps;
24     }
25     public Integer getId() {
26         return id;
27     }
28     public void setId(Integer id) {
29         this.id = id;
30     }
31     public String getDepartmentName() {
32         return departmentName;
33     }
34     public void setDepartmentName(String departmentName) {
35         this.departmentName = departmentName;
36     }
37     @Override
38     public String toString() {
39         return "Department [id=" + id + ", departmentName=" + departmentName
40                 + "]";
41     }
42     
43     
44 
45 }

创建dao接口:

 1 package com.atguigu.mybatis.dao;
 2 
 3 import java.util.List;
 4 
 5 import org.apache.ibatis.annotations.Param;
 6 
 7 import com.atguigu.mybatis.bean.Employee;
 8 
 9 public interface EmployeeMapperDynamicSQL {
10     
11     public List<Employee> getEmpsTestInnerParameter(Employee employee);
12     
13     //携带了哪个字段查询条件就带上这个字段的值
14     public List<Employee> getEmpsByConditionIf(Employee employee);
15     
16     public List<Employee> getEmpsByConditionTrim(Employee employee);
17     
18     public List<Employee> getEmpsByConditionChoose(Employee employee);
19     
20     public void updateEmp(Employee employee);
21     
22     //查询员工id‘在给定集合中的
23     public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids);
24     
25     public void addEmps(@Param("emps")List<Employee> emps);
26 
27 }

创建xml文件:

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <!DOCTYPE mapper
  3  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5 <mapper namespace="com.atguigu.mybatis.dao.EmployeeMapperDynamicSQL">
  6     <!-- 
  7 ? if:判断
  8 ? choose (when, otherwise):分支选择;带了break的swtich-case
  9     如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个
 10 ? trim 字符串截取(where(封装查询条件), set(封装修改条件))
 11 ? foreach 遍历集合
 12      -->
 13      <!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
 14      <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
 15      <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
 16          select * from tbl_employee
 17          <!-- where -->
 18          <where>
 19              <!-- test:判断表达式(OGNL)
 20              OGNL参照PPT或者官方文档。
 21                     c:if  test
 22              从参数中取值进行判断
 23              
 24              遇见特殊符号应该去写转义字符:
 25              && 26              -->
 27              <if test="id!=null">
 28                  id=#{id}
 29              </if>
 30              <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
 31                  and last_name like #{lastName}
 32              </if>
 33              <if test="email!=null and email.trim()!=&quot;&quot;">
 34                  and email=#{email}
 35              </if> 
 36              <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
 37              <if test="gender==0 or gender==1">
 38                   and gender=#{gender}
 39              </if>
 40          </where>
 41      </select>
 42      
 43      <!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
 44      <select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.bean.Employee">
 45          select * from tbl_employee
 46          <!-- 后面多出的and或者or where标签不能解决 
 47          prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
 48                  prefix给拼串后的整个字符串加一个前缀 
 49          prefixOverrides="":
 50                  前缀覆盖: 去掉整个字符串前面多余的字符
 51          suffix="":后缀
 52                  suffix给拼串后的整个字符串加一个后缀 
 53          suffixOverrides=""
 54                  后缀覆盖:去掉整个字符串后面多余的字符
 55                  
 56          -->
 57          <!-- 自定义字符串的截取规则 -->
 58          <trim prefix="where" suffixOverrides="and">
 59              <if test="id!=null">
 60                  id=#{id} and
 61              </if>
 62              <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
 63                  last_name like #{lastName} and
 64              </if>
 65              <if test="email!=null and email.trim()!=&quot;&quot;">
 66                  email=#{email} and
 67              </if> 
 68              <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
 69              <if test="gender==0 or gender==1">
 70                   gender=#{gender}
 71              </if>
 72          </trim>
 73      </select>
 74      
 75      <!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
 76      <select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee">
 77          select * from tbl_employee 
 78          <where>
 79              <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->
 80              <choose>
 81                  <when test="id!=null">
 82                      id=#{id}
 83                  </when>
 84                  <when test="lastName!=null">
 85                      last_name like #{lastName}
 86                  </when>
 87                  <when test="email!=null">
 88                      email = #{email}
 89                  </when>
 90                  <otherwise>
 91                      gender = 0
 92                  </otherwise>
 93              </choose>
 94          </where>
 95      </select>
 96      
 97      <!--public void updateEmp(Employee employee);  -->
 98      <update id="updateEmp">
 99          <!-- Set标签的使用 -->
100          update tbl_employee 
101         <set>
102             <if test="lastName!=null">
103                 last_name=#{lastName},
104             </if>
105             <if test="email!=null">
106                 email=#{email},
107             </if>
108             <if test="gender!=null">
109                 gender=#{gender}
110             </if>
111         </set>
112         where id=#{id} 
113 <!--         
114         Trim:更新拼串
115         update tbl_employee 
116         <trim prefix="set" suffixOverrides=",">
117             <if test="lastName!=null">
118                 last_name=#{lastName},
119             </if>
120             <if test="email!=null">
121                 email=#{email},
122             </if>
123             <if test="gender!=null">
124                 gender=#{gender}
125             </if>
126         </trim>
127         where id=#{id}  -->
128      </update>
129      
130      <!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids);  -->
131      <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
132          select * from tbl_employee
133          <!--
134              collection:指定要遍历的集合:
135                  list类型的参数会特殊处理封装在map中,map的key就叫list
136              item:将当前遍历出的元素赋值给指定的变量
137              separator:每个元素之间的分隔符
138              open:遍历出所有结果拼接一个开始的字符
139              close:遍历出所有结果拼接一个结束的字符
140              index:索引。遍历list的时候是index就是索引,item就是当前值
141                            遍历map的时候index表示的就是map的key,item就是map的值
142              
143              #{变量名}就能取出变量的值也就是当前遍历出的元素
144            -->
145          <foreach collection="ids" item="item_id" separator=","
146              open="where id in(" close=")">
147              #{item_id}
148          </foreach>
149      </select>
150      
151      <!-- 批量保存 -->
152      <!--public void addEmps(@Param("emps")List<Employee> emps);  -->
153      <!--mysql下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
154     <insert id="addEmps">
155          insert into tbl_employee(
156              <include refid="insertColumn"></include>
157          ) 
158         values
159         <foreach collection="emps" item="emp" separator=",">
160             (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
161         </foreach>
162      </insert><!--   -->
163      
164      <!-- 这种方式需要数据库连接属性allowMultiQueries=true165          这种分号分隔多个sql可以用于其他的批量操作(删除,修改) -->
166      <!-- <insert id="addEmps">
167          <foreach collection="emps" item="emp" separator=";">
168              insert into tbl_employee(last_name,email,gender,d_id)
169              values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
170          </foreach>
171      </insert> -->
172      
173      <!-- Oracle数据库批量保存: 
174          Oracle不支持values(),(),()
175          Oracle支持的批量方式
176          1、多个insert放在begin - end里面
177              begin
178                 insert into employees(employee_id,last_name,email) 
179                 values(employees_seq.nextval,‘test_001‘,‘[email protected]);
180                 insert into employees(employee_id,last_name,email) 
181                 values(employees_seq.nextval,‘test_002‘,‘[email protected]);
182             end;
183         2、利用中间表:
184             insert into employees(employee_id,last_name,email)
185                select employees_seq.nextval,lastName,email from(
186                       select ‘test_a_01‘ lastName,‘test_a_e01‘ email from dual
187                       union
188                       select ‘test_a_02‘ lastName,‘test_a_e02‘ email from dual
189                       union
190                       select ‘test_a_03‘ lastName,‘test_a_e03‘ email from dual
191                )    
192      -->
193      <insert id="addEmps" databaseId="oracle">
194          <!-- oracle第一种批量方式 -->
195          <!-- <foreach collection="emps" item="emp" open="begin" close="end;">
196              insert into employees(employee_id,last_name,email) 
197                 values(employees_seq.nextval,#{emp.lastName},#{emp.email});
198          </foreach> -->
199          
200          <!-- oracle第二种批量方式  -->
201          insert into employees(
202              <!-- 引用外部定义的sql -->
203              <include refid="insertColumn">
204                  <property name="testColomn" value="abc"/>
205              </include>
206          )
207                  <foreach collection="emps" item="emp" separator="union"
208                      open="select employees_seq.nextval,lastName,email from("
209                      close=")">
210                      select #{emp.lastName} lastName,#{emp.email} email from dual
211                  </foreach>
212      </insert>
213      
214      <!-- 两个内置参数:
215          不只是方法传递过来的参数可以被用来判断,取值。。。
216          mybatis默认还有两个内置参数:
217          _parameter:代表整个参数
218              单个参数:_parameter就是这个参数
219              多个参数:参数会被封装为一个map;_parameter就是代表这个map
220          
221          _databaseId:如果配置了databaseIdProvider标签。
222              _databaseId就是代表当前数据库的别名oracle
223       -->
224       
225       <!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
226       <select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
227               <!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
228               <bind name="_lastName" value="‘%‘+lastName+‘%‘"/>
229               <if test="_databaseId==‘mysql‘">
230                   select * from tbl_employee
231                   <if test="_parameter!=null">
232                       where last_name like #{lastName}
233                   </if>
234               </if>
235               <if test="_databaseId==‘oracle‘">
236                   select * from employees
237                   <if test="_parameter!=null">
238                       where last_name like #{_parameter.lastName}
239                   </if>
240               </if>
241       </select>
242       
243       <!-- 
244           抽取可重用的sql片段。方便后面引用 
245           1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
246           2、include来引用已经抽取的sql:
247           3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
248                   include-property:取值的正确方式${prop},
249                   #{不能使用这种方式}
250       -->
251       <sql id="insertColumn">
252               <if test="_databaseId==‘oracle‘">
253                   employee_id,last_name,email
254               </if>
255               <if test="_databaseId==‘mysql‘">
256                   last_name,email,gender,d_id
257               </if>
258       </sql>
259       
260 </mapper>

 

以上是关于mybatis之动态SQL的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis 学习笔记总结

MyBatis-05-笔记

Mybatis -- 动态Sql 环境搭建

MyBatis动态SQL标签用法

mybatis学习(39):动态sql片段

mybatis动态sql片段与分页,排序,传参的使用