编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
Maven版本:apache-maven-3.6.3
Mybatis版本:3.5.6
关于XXXMapper接口对应的映射文件里SQL中的注释
语法
①方式一
//mysql的注释
-- 1=1
②方式二
//xml的注释
❓使用这两种注释方式各有什么不同呢?
请看如下测试
代码示例如下:
①使用第一种注释
<select id="selectEmpByopr" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
WHERE
-- 1=1
<if test="id !=null">
and id=#{id}
if>
<if test="lastName != null">
and last_name=#{lastName}
if>
<if test="email != null">
and email=#{email}
if>
<if test="salary != null">
and last_name=#{salary}
if>
select>
②使用第二种注释
<select id="selectEmpByopr" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
WHERE
<if test="id !=null">
and id=#{id}
if>
<if test="lastName != null">
and last_name=#{lastName}
if>
<if test="email != null">
and email=#{email}
if>
<if test="salary != null">
and last_name=#{salary}
if>
select>
结论
通过以上二者运行测试结果对比,所以在需要使用注释时,推荐使用第二种注释方式
定义
❗注意
用法案例
不指定查询条件,查询对应员工信息,即当你传入id,程序就根据id去查,传入什么条件,就去根据此条件去查(多个条件不确定)
代码示例如下
①在EmployeeMapper接口下书写相应的方法
//动态的sql方式,即不指定查询条件,查询对应员工信息
public List<Employee> selectEmpByopr(Employee employee);
②在EmployeeMapper接口相应的sql
<select id="selectEmpByopr" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
WHERE
<if test="id !=null">
and id=#{id}
if>
<if test="lastName != null">
and last_name=#{lastName}
if>
<if test="email != null">
and email=#{email}
if>
<if test="salary != null">
and last_name=#{salary}
if>
select>
③测试
@Test
public void test01(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//动态参数(无参会报错,没有第一个参数也会报错)
Employee employee=new Employee();
List<Employee> employees = employeeMapper.selectEmpByopr(employee);
//遍历集合employees
for (Employee employee1 : employees) {
System.out.println(employee1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
❓但是这样会出现一个问题,即不传参会报错,没有第一个参数也会报错
原因分析
不传参时,mybatis解析sql的过程中走到where的部分,无参,会进入where里,但不会执行里面的任意if判断,where后没有任何赋值表达式,此sql为非法sql,故报错。没有第一个参数时也会报类似的问题。
解决方案
①在第二步中的where里加上 1=1,作为条件恒等式(老版本的解决措施)
②使用where标签
代码示例如下:
<select id="selectEmpByopr" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
<where>
<if test="id !=null">
and id=#{id}
if>
<if test="lastName != null">
and last_name=#{lastName}
if>
<if test="email != null">
and email=#{email}
if>
<if test="salary != null">
and last_name=#{salary}
if>
where>
select>
功能
用于完成简单的判断
示例代码如下:
//如果属性id不为空,就将传入的参数id赋值给sql中的字段id
<if test="id !=null">
id=#{id}
if>
功能:
用于解决where关键字及where后第一个and或or的问题
示例代码如下:
<where>
<if test="id !=null">
and id=#{id}
if>
<if test="lastName != null">
and last_name=#{lastName}
if>
<if test="email != null">
and email=#{email}
if>
<if test="salary != null">
and last_name=#{salary}
if>
where>
功能
可以在条件判断完的SQL语句前后添加或者去掉指定的字符
属性
prefix
:添加前缀prefixOverrides
:去掉前缀suffix
:添加后缀suffixOverrides
:去掉后缀用法案例
不指定查询条件,查询对应员工信息(trim标签优化版)
代码示例如下:
①在EmployeeMapper接口定义相应的方法
//不指定查询条件,查询对应员工信息
public List<Employee> selectEmpByEmpTrim(Employee employee);
②在EmployeeMapper接口对应的映射文件中定义相应的sql
<select id="selectEmpByEmpTrim" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
<trim prefix="where" suffixOverrides="and">
<if test="id !=null">
id=#{id} and
if>
<if test="lastName != null">
last_name=#{lastName} and
if>
<if test="email != null">
email=#{email} and
if>
<if test="salary != null">
salary=#{salary} and
if>
trim>
select>
③测试
@Test
public void test02(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//动态参数
Employee employee=new Employee();
/* employee.setLastName("jack");
employee.setSalary(5600.0);
*/
List<Employee> employees = employeeMapper.selectEmpByEmpTrim(employee);
//遍历集合employees
for (Employee employee1 : employees) {
System.out.println(employee1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
trim标签运行流程详解
功能
主要用于解决set关键字及多出一个【,】问题
用法案例
修改员工的信息
代码示例如下:
①在EmployeeMapper接口中定义修改员工的信息的方法
//修改员工的信息
public void updateEmp(Employee employee);
②在EmployeeMapper接口对应的映射文件中书写相应的sql
问题版(会出现多一个【,】问题
)
update
tbl_employee
set
last_name=#{lastName} ,
email=#{email} ,
salary=#{salary} ,
where
id=#{id}
set标签解决问题版
<update id="updateEmp">
update
tbl_employee
<set>
<if test="lastName != null">
last_name=#{lastName} ,
if>
<if test="email != null">
email=#{email} ,
if>
<if test="salary != null">
salary=#{salary} ,
if>
set>
where
id=#{id}
update>
③测试
@Test
public void test03(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//动态参数
Employee employee=new Employee();
employee.setId(1);
employee.setLastName("tom");
employee.setSalary(16800.0);
employeeMapper.updateEmp(employee);
xml
} catch (IOException e) {
e.printStackTrace();
}
}
使用问题版的sql进行测试
使用set标签解决问题版的sql进行测试
功能
类似java中if-else【switch-case】结构
应用场景
应用于单个条件不确定的业务场景
用法案例
不指定查询条件,查询对应的员工信息(单个条件不确定的)
代码示例如下:
①在EmployeeMapper接口书写相应的方法
//不指定查询条件,查询对应员工信息(单个条件不确定的)
public List<Employee> selectEmpByOneOpr(int empId);
②在EmployeeMapper接口对应的映射文件中书写相应的sql
<select id="selectEmpByOneOpr" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
<where>
<choose>
<when test="id !=null">
id=#{id}
when>
<when test="lastName != null">
last_name=#{lastName}
when>
<when test="email != null">
email=#{email}
when>
<otherwise>
salary=#{salary}
otherwise>
choose>
where>
select>
③测试
@Test
public void test04(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = employeeMapper.selectEmpByOneOpr(1);
System.out.println(employees);
} catch (IOException e) {
e.printStackTrace();
}
}
功能
类似java中for循环
标签属性
collection
:要迭代的集合item
:当前从集合中迭代出的元素separator
:元素与元素之间的分隔符open
:开始字符close
:结束字符应用场景
①遍历迭代
用法案例
通过多个id获取员工的信息 【EmpIds:员工id的集合】
代码示例如下:
a.在EmployeeMapper接口定义相应的方法
/**
* 通过多个id获取员工的信息 【EmpIds:员工id的集合】
* @param EmpIds
* @return
*/
public List<Employee> selectEmpByIds(@Param("ids") List<Integer> EmpIds);
b.在EmployeeMapper接口对应的映射文件中定义相应的sql
<select id="selectEmpByIds" resultType="employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
<where>
`id` in
(
<foreach collection="ids" item="id" separator=",">
#{id}
foreach>
)
where>
select>
c.测试
@Test
public void test04(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = employeeMapper.selectEmpByOneOpr(1);
System.out.println(employees);
} catch (IOException e) {
e.printStackTrace();
}
}
②批量导入
用法案例
批量添加员工数据
代码示例如下:
a.在EmployeeMapper接口定义相应的方法
//批量添加员工数据
public void batchInsertEmp(@Param("emps") List<Employee> employees);
b.在EmployeeMapper接口对应的映射文件中定义相应的sql
// 批量添加员工数据,使用insert标签书写相应的sql
<insert id="batchInsertEmp">
insert into
tbl_employee(last_name,email,salary)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.salary})
foreach>
insert>
c.测试
@Test
public void test06(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//定义要添加的员工集合
List<Employee> list=new ArrayList<>();
list.add(new Employee("zhangsan","[email protected]",6700.0));
list.add(new Employee("wangwu","[email protected]",9700.0));
employeeMapper.batchInsertEmp(list);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
功能
提取可重用SQL片段
❗注意
该SQL片段可以是一个完整的sql语句,也可以是一个sql语句中的某个片段)
用法案例
使用sql标签对3.6小节中的应用场景1的案例里映射文件里的的”select xxx,xxxx,xxx from
xxxx”部分提取出来,作为一个可重用的sql片段,在select>标签内引入该sql片段
代码示例如下:
①使用sql标签抽取映射文件中”select xxx,xxxx,xxx from xxxx”部分片段作为可重用的sql片段
<sql id="select_employee">
SELECT
`id`,
`last_name`,
`email`,
`salary`,
`dept_id`
FROM
`tbl_employee`
sql>
<select id="selectEmpByIds" resultType="employee">
<include refid="select_employee">include>
<where>
`id` in
(
<foreach collection="ids" item="id" separator=",">
#{id}
foreach>
)
where>
select>
②测试运行