mybatis-动态sql
动态sql
• if:判断
• choose (when, otherwise):分支选择;
• trim 字符串截取(where(封装查询条件), set(封装修改条件))
• foreach 遍历集合**
1、if的使用(&OGNL):
<!-- test:判断表达式(OGNL)
c:if test
从参数中取值进行判断
遇见特殊符号应该去写转义字符:
&:(&)
“:"
-->
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null && lastName!=""">
and last_name like #{lastName}
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
and gender=#{gender}
</if>
- 在if查询时,如果某些条件没带可能sql拼装会有问题
(例如出现select * from tbl_employee where and last_name=?这种问题)
解决方案:
(1)给where后加入 1=1永真判断。
select * from tbl_employee
<!--test:判断表达式-->
where 1=1
<if test="id!=null">
id=#{id}
</if
(2)mybatis使用where标签(封装查询条件)来将所有的查询条件包括在内。
select * from tbl_employee
<!--test:判断表达式-->
<where
<if test="id!=null">
id=#{id}
</if
</where
where只会去掉第一个多出来的and或者or.拼接后后面可能也会多出and或者or,可以使用trim.
(3)trim自定字符串截取
<trim> prefix="" (前缀:trim标签体中是整个字符串拼接后的结果。
prefix给拼串后的整个字符串加一个前缀)
prefixOverrides=" " (前缀覆盖:去掉整个字符串前面多余的字符)
suffix=" " (后缀:给拼串后的整个字符串加一个后缀)
suffixOverrides=" " (后缀覆盖:去掉整个字符串后面多余的字符)
<trim>
2、choose分支选择:
choose (when,otherwise) :分支选择;带了break的swtich-case,如果带了id就用id查,如果带了Name就用Name查;只会进入其中一个。
<select id="getEmpsByCondtionChoose" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee
<where>
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<otherwise>
gender =0
</otherwise>
</choose>
</where>
</select>
3、set 与if结合的动态更新
set(封装修改条件)
<!-- Set标签的使用
(假如test类中语句如下
Employee employee=new Employee(1,"admin",null,null);
可以去除sql中的多余逗号等)
update tbl_employee
<set>
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}-->
4、foreach
(1)foreach遍历集合
<!-- public List<Employee> getEmpsByConditionForeach(List<Integer> ids);-->
<select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee where id in
<!--
collection :指定要遍历的集合;
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list时候,index是索引,item是当前值
遍历map时候表示的是map的key,item是map的值
#{变量名}就能取出变量的值,也就是当前遍历出的元素
-->
<foreach collection="ids" item="item_id" separator=","
open="(" close=")">
#{item_id}
</foreach>
</select>
(2)mysql下foreach批量插入的两种方式
批量保存
1、
<!--public void addEmps(@Param("emps")List<Employee> emps);-->
<!-foreach遍历,mysql支持values(),(),()语法--->
<insert id="addEmps">
INSERT into tbl_employee(last_name,email,gender,d_id)
VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
<!--test样例:-->
List<Employee> emps=new ArrayList<>();
emps.add(new Employee(null,"smith","smith@guigu.com","1",new Department(1)));
emps.add(new Employee(null,"allen","allen@guigu.com","0",new Department(1)));
mapper.addEmps(emps);
openSession.commit();
2、
<!--mysql支持多个sql语句(数据库连接属性,
allowMultiQueries允许使用;分隔多条查寻)
但需要更改配置资源allowMultiQueries=true,不太使用
这种分号分隔多个sql可以用于其他的批量操作(删除,修改)-->
<insert id="addEmps">
<foreach collection="emps" item="emp" separator=";">
insert into tbl_employee(last_name,email,gender,d_id)
values (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
5、内置参数:_parameter&_databaseId
不只是方法传递过来的参数可以被用来判断,取值…
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装成一个map;_parameter就代表这个map
_databaseId:如果配置了databaseIdProvider标签。
_databaseId就是代表当前数据库的别名(mysql)。
<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);-->
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
<if test="_databaseId=='mysql'">
<!--使用多个条件(where)时需要判断传参employee是否为空
_parameter就代表employee对象
-->
select * from tbl_employee
<if test="_parameter!=null">
where last_name=#{_parameter.lastName}
</if>
</if>
<if test="_databaseId=='oracle'">
/*select * from employees*/
</if>
</select>
6、_bind_绑定
<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);-->
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
<!--bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值-->
<bind name="_lastName" value="'_'+lastName+'%'"/>
<if test="_databaseId=='mysql'">
<!--使用多个条件(where)时需要判断传参employee是否为空-->
select * from tbl_employee
<if test="_parameter!=null">
where last_name like #{_lastName}
</if>
</if>
<if test="_databaseId=='oracle'">
/*select * from employees*/
</if>
</select>
在模糊查询中可以使用bind标签拼接OGNL表达式,但在实际使用中一般在传参时便拼接好了字符串
EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
Employee employee2=new Employee();
employee2.setLastName("%e%");
List<Employee> list = mapper.getEmpsTestInnerParameter(employee2);
for(Employee employee : list)
{
System.out.println(employee);
}
7、sql标签_抽取可重用的sql片段
<!--抽取可重用的sql片段
1、sql抽取:将经常要查询的列名,或者插入用的列名抽取出来方便引用
2、include标签来引用已经抽取的sql
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
include-property取值的正确方式:${prop},
#{}(用来取传参的参数)不可以使用
-->
<sql id="insertColumn">
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
<if test="_databaseId=='oracle'">
<!--last_name,email,gender,d_id-->
</if>
</sql>
<insert id="addEmps">
INSERT into tbl_employee(
<!--引用外部定义的sql-->
<include refid="insertColumn">
<property name="testColomn" value="***"/>
</include>
)
VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
<!--使用自定义的属性来增加要查询的属性名及内容-->
DEBUG 02-08 16:14:46,861 ==> Preparing: INSERT into tbl_employee( last_name,email,gender,d_id,*** ) VALUES (?,?,?,?) , (?,?,?,?)