简介
- 动态SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作
- 动态SQL元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似
- MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作
- If
- choose (when, otherwise)
- trim (where, set)
- foreach
OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。 类似于我们的EL,SpEL等
功能 | 参数 |
---|---|
访问对象属性 | person.name |
调用方法 | person.getName() |
person.getName() | @java.lang.Math@PI @java.util.UUID@randomUUID() |
调用构造方法 | new com.atguigu.bean.Person(‘admin’).name |
运算符 | +,-*,/,% |
逻辑运算符 | in,not in,>,>=,<,<=,==,!= |
注意:xml中特殊符号如”,>,<等这些都需要使用转义字符
项目结构
数据准备
项目结构
Department
package com.hph.mybatis.beans;
import java.util.List;
public class Department {
private Integer id;
private String departmentName ;
private List<Employee> emps ;
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
@Override
public String toString() {
return "Department [id=" + id + ", departmentName=" + departmentName + "]";
}
}
Employee
package com.hph.mybatis.beans;
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
private Department dept;
public void setDept(Department dept) {
this.dept = dept;
}
public Department getDept() {
return dept;
}
public Employee() {
}
public Employee(Integer id, String lastName, String email, Integer gender, Department dept) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.dept = dept;
}
public Employee(Integer id, String lastName, String email, Integer gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
}
}
EmployeeMapperDynamicSQL
package com.hph.mybatis.dao;
import com.hph.mybatis.beans.Employee;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface EmployeeMapperDynamicSQL {
public List<Employee> getEmpsByConditionIfWhere(Employee condition);
public List<Employee> getEmpsByConditionTrim(Employee condition);
public void updateEmpByConitionSet(Employee condition);
public List<Employee> getEmpsByConditionChoose(Employee condition);
public List<Employee> getEmpsByIds(@Param("ids") List<Integer> ids);
//批量操作: 删除 修改 添加
public void addEmps(@Param("emps") List<Employee> emps);
}
EmployeeMapperDynamicSQL.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.hph.mybatis.dao.EmployeeMapperDynamicSQL">
<!-- public List<Employee> getEmpsByConditionIfWhere(Employee Condition); -->
<select id="getEmpsByConditionIfWhere" resultType="com.hph.mybatis.beans.Employee">
select id, last_name, email, gender
from tbl_employee
<!-- where 1=1 -->
<where> <!-- 在SQL语句中提供WHERE关键字, 并且要解决第一个出现的and 或者是 or的问题 -->
<if test="id!=null">
and id = #{id }
</if>
<if test="lastName!=null&&lastName!=""">
and last_name = #{lastName}
</if>
<if test="email!=null and email.trim()!=''">
and email = #{email}
</if>
<if test="gender==0 or gender==1">
and gender = #{gender}
</if>
</where>
</select>
<select id="getEmpsByConditionTrim" resultType="com.hph.mybatis.beans.Employee">
select id, last_name, email, gender
from tbl_employee
<!--
prefix: 添加一个前缀
pprefixOverrides:覆盖/去掉一个前缀
ssuffxi:添加一个后缀
suffixOverrides:覆盖/去掉一个后缀
-->
<trim prefix="where" suffixOverrides="and|or">
<if test="id!=null">
id = #{id } and
</if>
<if test="lastName!=null&&lastName!=""">
last_name = #{lastName} and
</if>
<if test="email!=null and email.trim()!=''">
email = #{email} or
</if>
<if test="gender==0 or gender==1">
gender = #{gender}
</if>
</trim>
</select>
<!--public void updateEmpByConitionSet(Employee condition);-->
<update id="updateEmpByConitionSet">
update tbl_employee
<set>
<if test="lastName!=null">
last_name = #{lastName},
</if>
<if test="email!=null">
email = #{email},
</if>
<if test="gender==0 or gender==1">
gender= #{gender},
</if>
</set>
where id = #{id}
</update>
<!-- public void updateEmpByConitionSet(Employee condition);-->
<select id="getEmpsByConditionChoose" resultType="com.hph.mybatis.beans.Employee">
select id,last_name,email,gender
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>
gender = 0
</otherwise>
</choose>
</select>
<!-- public List<Employee> getEmpsByIds(@Param("ids")List<Integer> ids);-->
<select id="getEmpsByIds" resultType="com.hph.mybatis.beans.Employee">
<!--
foreach:
collection:指定要迭代的几乎额
item:当前集合中迭代出的元素
open:指定一个开始字符
close:指定一个结束字符
separtor:元素与元素之间的分隔符
-->
select id,last_name,email,gender from tbl_employee
where id in
<foreach collection="ids" item="currId" open="(" close=")" separator=",">
#{currId}
</foreach>
</select>
<!-- public void addEmps(@Param("emps") List<Employee> emps)
添加:insert into tbl_employee(x,x,x) values(?,?,?),(?,?<?),(?,?,?)
删除:delete from tbl_employee where id in (?,?,?)
修改:update tbl_employee set last_name = #{lastName }...where id = #{id}}
update tbl_employee set last_name = #{lastName }...where id = #{id}}
update tbl_employee set last_name = #{lastName }...where id = #{id}}
默认情况下,JDBCb允许将多条分号SQL通过;平日你改成一个字符串
;-->
<insert id="addEmps">
insert into tbl_employee(last_name, email,gender ) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender})
</foreach>
</insert>
</mapper>
TestMybatisDynamicSQL
package com.hph.mybatis.test;
import com.hph.mybatis.beans.Employee;
import com.hph.mybatis.dao.EmployeeMapperDynamicSQL;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class TestMybatisDynamicSQL {
public SqlSessionFactory getSqlSessionFactory() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
@Test
public void testIf() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession();
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
/* condition.setId(5);
condition.setLastName("清风_笑丶");*/
//condition.setEmail("qfx@sina.com");
//condition.setGender(1);
List<Employee> emps = mapper.getEmpsByConditionIfWhere(condition);
System.out.println(emps);
} finally {
session.close();
}
}
@Test
public void testTrim() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession();
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
condition.setId(5);
condition.setLastName("清风_笑丶");
condition.setEmail("qfx@gmail.com");
//condition.setGender(1);
List<Employee> emps = mapper.getEmpsByConditionTrim(condition);
System.out.println(emps);
} finally {
session.close();
}
}
@Test
public void testSet() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
condition.setId(5);
condition.setLastName("清风_笑丶testSet");
condition.setEmail("qf_x@qq.com");
// condition.setGender(1);
mapper.updateEmpByConitionSet(condition);
} finally {
session.close();
}
}
@Test
public void testChoose() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
condition.setId(1);
condition.setLastName("清风_笑丶testChoose");
condition.setEmail("qf_xtestChoose@gmail.com");
//condition.setGender(1);
List<Employee> emps = mapper.getEmpsByConditionChoose(condition);
System.out.println(emps);
} finally {
session.close();
}
}
@Test
public void testForeach() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
List<Integer> ids = new ArrayList<Integer>();
ids.add(5);
ids.add(6);
ids.add(7);
List<Employee> emps = mapper.getEmpsByIds(ids);
System.out.println(emps);
} finally {
session.close();
}
}
@Test
public void testBatch() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
List<Employee> emps = new ArrayList<Employee>();
emps.add(new Employee(null, "清风笑_testBatch1", "qfx_testBatch1@sina.com", 1));
emps.add(new Employee(null, "清风笑_testBatch2", "qfx_testBatch2@sina.com", 0));
emps.add(new Employee(null, "清风笑_testBatch3", "qfx_testBatch3@sina.com", 1));
mapper.addEmps(emps);
} finally {
session.close();
}
}
}
if where
If用于完成简单的判断.
Where用于解决SQL语句中where关键字以及条件中第一个and或者or的问题
<!-- public List<Employee> getEmpsByConditionIfWhere(Employee Condition); -->
<select id="getEmpsByConditionIfWhere" resultType="com.hph.mybatis.beans.Employee">
select id, last_name, email, gender
from tbl_employee
<!-- where 1=1 -->
<where> <!-- 在SQL语句中提供WHERE关键字, 并且要解决第一个出现的and 或者是 or的问题 -->
<if test="id!=null">
and id = #{id }
</if>
<if test="lastName!=null&&lastName!=""">
and last_name = #{lastName}
</if>
<if test="email!=null and email.trim()!=''">
and email = #{email}
</if>
<if test="gender==0 or gender==1">
and gender = #{gender}
</if>
</where>
</select>
public void testIf() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession();
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
List<Employee> emps = mapper.getEmpsByConditionIfWhere(condition);
System.out.println(emps);
} finally {
session.close();
}
}
@Test
public void testIf() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession();
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
condition.setId(1001);
List<Employee> emps = mapper.getEmpsByConditionIfWhere(condition);
System.out.println(emps);
} finally {
session.close();
}
}
trim
<select id="getEmpsByConditionTrim" resultType="com.hph.mybatis.beans.Employee">
select id, last_name, email, gender
from tbl_employee
<!--
prefix: 添加一个前缀
pprefixOverrides:覆盖/去掉一个前缀
ssuffxi:添加一个后缀
suffixOverrides:覆盖/去掉一个后缀
-->
<trim prefix="where" suffixOverrides="and|or">
<if test="id!=null">
id = #{id } and
</if>
<if test="lastName!=null&&lastName!=""">
last_name = #{lastName} and
</if>
<if test="email!=null and email.trim()!=''">
email = #{email} or
</if>
<if test="gender==0 or gender==1">
gender = #{gender}
</if>
</trim>
</select>
@Test
public void testTrim() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession();
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
List<Employee> emps = mapper.getEmpsByConditionTrim(condition);
System.out.println(emps);
} finally {
session.close();
}
}
set
set 主要是用于解决修改操作中SQL语句中可能多出逗号的问题.
<update id="updateEmpByConitionSet">
update tbl_employee
<set>
<if test="lastName!=null">
last_name = #{lastName},
</if>
<if test="email!=null">
email = #{email},
</if>
<if test="gender==0 or gender==1">
gender= #{gender},
</if>
</set>
where id = #{id}
</update>
@Test
public void testSet() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
condition.setId(1001);
condition.setLastName("清风笑丶");
condition.setEmail("qf_x@gmail.com");
mapper.updateEmpByConitionSet(condition);
} finally {
session.close();
}
}
choose(when、otherwise)
choose 主要是用于分支判断,类似于java中的switch case,只会满足所有分支中的一个
<!-- public void updateEmpByConitionSet(Employee condition);-->
<select id="getEmpsByConditionChoose" resultType="com.hph.mybatis.beans.Employee">
select id,last_name,email,gender
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>
gender = 0
</otherwise>
</choose>
</select>
@Test
public void testChoose() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
List<Employee> emps = mapper.getEmpsByConditionChoose(condition);
System.out.println(emps);
} finally {
session.close();
}
}
foreach
foreach 主要用户循环迭代
collection: 要迭代的集合
item: 当前从集合中迭代出的元素
open: 开始字符
close:结束字符
separator: 元素与元素之间的分隔符
index:
迭代的是List集合: index表示的当前元素的下标
迭代的Map集合: index表示的当前元素的key
<!-- public List<Employee> getEmpsByIds(@Param("ids")List<Integer> ids);-->
<select id="getEmpsByIds" resultType="com.hph.mybatis.beans.Employee">
<!--
foreach:
collection:指定要迭代的几乎额
item:当前集合中迭代出的元素
open:指定一个开始字符
close:指定一个结束字符
separtor:元素与元素之间的分隔符
-->
select id,last_name,email,gender from tbl_employee where id in
<foreach collection="ids" item="currId" open="(" close=")" separator=",">
#{currId}
</foreach>
</select>
@Test
public void testForeach() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
Employee condition = new Employee();
List<Integer> ids = new ArrayList<Integer>();
ids.add(1001);
ids.add(1002);
List<Employee> emps = mapper.getEmpsByIds(ids);
System.out.println(emps);
} finally {
session.close();
}
}
<!--
//批量操作: 删除 修改 添加
public void addEmps(@Param("emps") List<Employee> emps);-->
<insert id="addEmps">
insert into tbl_employee(last_name, email,gender ) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender})
</foreach>
</insert>
@Test
public void testBatch() throws Exception {
SqlSessionFactory ssf = getSqlSessionFactory();
SqlSession session = ssf.openSession(true);
try {
EmployeeMapperDynamicSQL mapper = session.getMapper(EmployeeMapperDynamicSQL.class);
List<Employee> emps = new ArrayList<Employee>();
emps.add(new Employee(null, "清风笑_testBatch1", "qfx_1@sina.com", 1));
emps.add(new Employee(null, "清风笑_testBatch2", "qfx_2@sina.com", 0));
emps.add(new Employee(null, "清风笑_testBatch3", "qfx_3@sina.com", 1));
mapper.addEmps(emps);
} finally {
session.close();
}
}
sql
sql 标签是用于抽取可重用的sql片段,将相同的,使用频繁的SQL片段抽取出来,单独定义,方便多次引用.
抽取SQL
<sql id="selectSQL">
select id , last_name, email ,gender from tbl_employee
</sql>
引用SQL:
<include refid="selectSQL"></include>