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 && lastName!="""> 31 and last_name like #{lastName} 32 </if> 33 <if test="email!=null and email.trim()!="""> 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 && lastName!="""> 63 last_name like #{lastName} and 64 </if> 65 <if test="email!=null and email.trim()!="""> 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=true; 165 这种分号分隔多个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的主要内容,如果未能解决你的问题,请参考以下文章