if标签
接口(EmployeeMapper.java)
package com.fish.dao;
import java.util.List;
import com.fish.pojo.Employee;
public interface EmployeeMapper {
/**
* 动态sql if拼接
* @Author ZFH
* @Date 2019年7月29日
*/
public List<Employee> selEmployeeByConationIf(Employee employee);
}
配置文件(EmployeeMapper.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fish.dao.EmployeeMapper">
<select id="selEmployeeByConationIf" resultType="com.fish.pojo.Employee">
select id, last_name lastName, email, gender from tbl_employee where
<!--
test:判断表达式(OGNL)
OGNL参照官方文档
test:
从参数中取值判断
对于特殊字符需要使用转义字符例如
&&:&&anm;或者and
"":"" 或者使用单引号
OGNL会进行紫都城的转换判断 例如下面的gender是String类型 但是我可以直接写 gender==1
-->
<if test="id != null">
id = #{id}
</if>
<if test="lastName != null and lastName !='' ">
and last_name like "%" #{lastName} "%"
</if>
<if test="email != null and email != '' ">
and email = #{email}
</if>
<if test="gender == 0 or gender == 1">
and gender = #{gender}
</if>
</select>
</mapper>
测试类
@org.junit.Test
public void test01() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(1);
employee.setLastName("2");
List<Employee> selEmployeeByConationIf = mapper.selEmployeeByConationIf(employee);
System.out.println(selEmployeeByConationIf);
//关闭Session
openSession.close();
}
运行结果
[Employee [id=1, lastName=222, email=ZFH_FISH@163.COM, gender=1]]
问题
有些同学可能发现问题了,如果id我不传只传lastName 那么mybatis进行sql拼接的时候会带上and,这样一来sql语句就会报错了,那么怎么解决呢,这里有两种方法,1:在动态sql之前的sql后面的where后面加上1=1 然后每一个条件都加上and,2:使用where标签
where标签
将上面的方法改造一下
接口(EmployeeMapper.xml)
<select id="selEmployeeByConationIf" resultType="com.fish.pojo.Employee">
select id, last_name lastName, email, gender from tbl_employee
<where>
<!--
test:判断表达式(OGNL)
OGNL参照官方文档
test:
从参数中取值判断
对于特殊字符需要使用转义字符例如
&&:&&anm;或者and
"":"" 或者使用单引号
OGNL会进行紫都城的转换判断 例如下面的gender是String类型 但是我可以直接写 gender==1
-->
<if test="id != null">
id = #{id}
</if>
<if test="lastName != null and lastName !='' ">
and last_name like "%" #{lastName} "%"
</if>
<if test="email != null and email != '' ">
and email = #{email}
</if>
<if test="gender == 0 or gender == 1">
and gender = #{gender}
</if>
</where>
</select>
测试类
@org.junit.Test
public void test01() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
//employee.setId(1);
employee.setLastName("2");
List<Employee> selEmployeeByConationIf = mapper.selEmployeeByConationIf(employee);
System.out.println(selEmployeeByConationIf);
//关闭Session
openSession.close();
}
运行结果
[Employee [id=1, lastName=222, email=ZFH_FISH@163.COM, gender=1], Employee [id=2, lastName=2, email=2, gender=1], Employee [id=5, lastName=22, email=lisi@163.com, gender=0]]
完美解决,通过这个例子我们知道,where标签可以帮我们把第一个多余的and或or去掉
上面的问题虽然解决了,但是还有一个问题,如果我的and是现在每个条件的后面的例如这样
<if test="id != null">
id = #{id} and
</if>
<if test="lastName != null and lastName !='' ">
last_name like "%" #{lastName} "%"
</if>
<if test="email != null and email != '' ">
and email = #{email} and
</if>
<if test="gender == 0 or gender == 1">
gender = #{gender}
</if>
那么sql又会报错了 这时候怎么解决呢 下面我们来介绍一下trim标签
trim(自定义字符串截取)
接口(EmployeeMapper.java)
/**
* 动态sql trim
* @Author ZFH
* @Date 2019年7月29日
*/
public List<Employee> selEmployeeByConationTrim(Employee employee);
配置文件(EmployeeMapper.xml)
<select id="selEmployeeByConationTrim"
resultType="com.fish.pojo.Employee">
select id, last_name lastName, email, gender from tbl_employee
<!-- trim:
prefix="":为拼接完的sql加一个前缀
prefixOverrides="":前缀覆盖,去掉整个字符串前面多余的字符串
suffix="" :为整个字符串加一个后缀
suffixOverrides="":后缀覆盖,去掉整个字符串后面多余的字符串
-->
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id = #{id} and
</if>
<if test="lastName != null and lastName !='' ">
last_name like "%" #{lastName} "%" and
</if>
<if test="email != null and email != '' ">
and email = #{email} and
</if>
<if test="gender == 0 or gender == 1">
gender = #{gender}
</if>
</trim>
</select>
测试类
@org.junit.Test
public void test02() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
//employee.setId(1);
employee.setLastName("2");
List<Employee> selEmployeeByConationIf = mapper.selEmployeeByConationTrim(employee);
System.out.println(selEmployeeByConationIf);
//关闭Session
openSession.close();
}
运行结果
[Employee [id=1, lastName=222, email=ZFH_FISH@163.COM, gender=1], Employee [id=2, lastName=2, email=2, gender=1], Employee [id=5, lastName=22, email=lisi@163.com, gender=0]]
再一次完美解决
choole分支选择
接口(EmployeeMapper.java)
/**
* 动态sql choose分支选择
* @Author ZFH
* @Date 2019年7月29日
*/
public List selEmployeeByConationChoose(Employee employee);
配置文件(EmployeeMapper.xml)
<select id="selEmployeeByConationChoose"
resultType="com.fish.pojo.Employee">
select id, last_name lastName, email, gender from tbl_employee
<where>
<choose>
<when test="id != null and id != '' ">
id = #{id}
</when>
<when test="lastName != null and lastName != '' ">
and last_name = #{lastName}
</when>
<when test="email != null and email != '' ">
and email = #{email}
</when>
<otherwise>
and gender = 0
</otherwise>
</choose>
</where>
</select>
测试类
@org.junit.Test
public void test03() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(1);
employee.setLastName("2");
List<Employee> selEmployeeByConationIf = mapper.selEmployeeByConationChoose(employee);
System.out.println(selEmployeeByConationIf);
//关闭Session
openSession.close();
}
运行结果
[Employee [id=1, lastName=222, email=ZFH_FISH@163.COM, gender=1]]
if与choose的区别
很多同学发现if与choose的效果一样,那为什么这两个都存在呢,其实这两个标签效果是不一样的,if标签是只要满足条件的都会拼接到sql上,而choose标签是只要有一个满足了条件,则只会拼接这一条,其他的都不执行了.
set(修改信息)
接口(EmployeeMapper.java)
public void selEmployeeByConationSet2(Employee employee);
配置文件(EmployeeMapper.xml)
<select id="selEmployeeByConationSet2"
resultType="com.fish.pojo.Employee">
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}
</select>
测试类
@org.junit.Test
public void test04() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setId(1);
employee.setLastName("张三1");
mapper.selEmployeeByConationSet2(employee);
openSession.commit();
//关闭Session
openSession.close();
}
使用trim完成修改
配置文件(其他的都一样)
<select id="selEmployeeByConationSet"
resultType="com.fish.pojo.Employee">
update tbl_employee
<trim prefix="set" suffixOverrides=",">
<if test="lastName != null">
last_name = #{lastName},
</if>
<if test="email != null">
email = #{email},
</if>
<if test="gender != null">
gender = #{gender}
</if>
</trim>
where id = #{id}
</select>
使用foreach遍历集合
接口(EmployeeMapper.java)
/**
* 动态sql foreach
* @Author ZFH
* @Date 2019年7月29日
*/
public List<Employee> selEmployeeByConationForeach(List<Integer> ids);
配置文件(EmployeeMapper.xml)
<select id="selEmployeeByConationForeach"
resultType="com.fish.pojo.Employee">
select * from tbl_employee where id in
<!--
collection:指定要遍历的集合,有三个取值分别是:array,list,collection分别对应了数组,集合,Map根据传入值的类型设置
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:拼接一个开始的字符串
close:拼接一个结束的字符串
index:索引.遍历list的时候index就是索引,item就是当前值
遍历map的时候,index是map的key,item是map的值
-->
<foreach collection="list" item="item_id" separator="," open="(" close=")" index="i">
#{item_id}
</foreach>
</select>
测试类
@org.junit.Test
public void test05() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
List<Employee> selEmployeeByConationForeach = mapper.selEmployeeByConationForeach(Arrays.asList(1,2,3));
System.out.println(selEmployeeByConationForeach);
//关闭Session
openSession.close();
}
运行结果
[Employee [id=1, lastName=张三1, email=ZFH_FISH@163.COM, gender=1], Employee [id=2, lastName=2, email=2, gender=1]]
foreach批量保存
接口EmployeeMapper.java
/**
* 动态sql foreach 批量添加
* @Author ZFH
* @Date 2019年7月29日
*/
public void addEmployee(@Param("emps") List<Employee> emps);
配置文件EmployeeMapper.xml
<insert id="addEmployee">
insert into tbl_employee(last_name,email,gender,d_id) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.department.id})
</foreach>
</insert>
测试类
@org.junit.Test
public void test06() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Employee> list = new ArrayList<Employee>();
Department department = new Department();
department.setId(1);
Department department2 = new Department();
department2.setId(2);
list.add(new Employee(null,"李四","zfh@163.com","1",department));
list.add(new Employee(null,"李四2","zfh@163.com","0",department2));
mapper.addEmployee(list);
openSession.commit();
//关闭Session
openSession.close();
}
运行结果
mybatis内置参数
mybatis有两个内置参数:_parameter,_databaseId
- _parameter:代表整个参数
- 单个参数: _parameter就是这个参数
- 多个参数: 参数会被封装为一个map: _parameter就是代表这个map
- _databaseId:如果配置了databaseIdProvider标签.
- _databaseId就是代表当前数据库的别名,例如: oracle
bind标签
接口(EmployeeMapper.java)
/**
* 使用bind标签
*/
public List<Employee> selEmpByNameBind(String lastName);
配置文件(EmployeeMapper.xml)
<select id="selEmpByNameBind" resultType="com.fish.pojo.Employee">
<bind name="_lastName" value="'%'+_parameter+'%'"/><!--这里取值用mybatis的内置参数取,用参数名取不到,不知道什么原因,有知道的小伙伴可以告知一下-->
select * from tbl_employee
<where>
last_name like #{_lastName}
</where>
</select>
测试类
@org.junit.Test
public void test07() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Employee> selEmpByNameBind = mapper.selEmpByNameBind("四");
System.out.println(selEmpByNameBind);
//关闭Session
openSession.close();
}
sql标签(抽取可重用sql片段)
接口(EmployeeMapper.java)
/**
* 使用sql标签
*/
public List<Employee> selEmpByNamesql(String lastName);
配置文件(EmployeeMapper.xml)
<!--
抽取可重用的sql片段,方便后面引用
1, sql抽取:京城将要查询的列名,或者插入用的列名抽取出来方便引用
2, include来引用已经抽取的sql
3, include还可以自定义一些property,sql标签内部就能使用自定义的属性
inclyde-property:取值的正确方式${prop},
不能用#{prop}这种方式
-->
<sql id="selColumn">
id,last_name,gender,${email2}<!--这里我觉得并没有实际的意义,可能是我还没有理解到精髓吧,以后了解了回来更新-->
</sql>
<select id="selEmpByNamesql" resultType="com.fish.pojo.Employee">
<bind name="_lastName" value="'%'+_parameter+'%'"/>
select
<include refid="selColumn">
<property name="email2" value="email"/>
</include>
from tbl_employee
<where>
last_name like "%" #{_lastName} ""
</where>
</select>
测试类
@org.junit.Test
public void test08() throws IOException {
//读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession openSession = sqlSessionFactory.openSession();
//调用getMapper方法获取该接口的实现类
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Employee> selEmpByNameBind = mapper.selEmpByNamesql("四");
System.out.println(selEmpByNameBind);
//关闭Session
openSession.close();
}
+
来源:https://blog.csdn.net/zzzffhh/article/details/99546389