> 文档中心 > Mybaits动态SQL课堂笔记

Mybaits动态SQL课堂笔记

Mybaits动态SQL

  • 一、动态SQL中的元素
    • 1.简介
    • 2. 实验环境
  • 二、条件查询操作
    • 1.if元素
    • 2.choose、when、otherwise元素
    • 3.where、trim元素
      • (1)where元素
      • (2)trim元素
  • 三、更新操作
    • 1.set元素实现
    • 2.trim元素实现
  • 测试代码
  • 四、复杂查询操作
    • 1.foreach元素及其属性
    • 2.foreach元素迭代数组
    • 3.foreach元素迭代List
    • 4.foreach元素迭代Map
  • 五、案例:学生信息查询系统

一、动态SQL中的元素

1.简介

用于在MyBatis的映射文件中动态组装SQL语句
主元素如下:**
在这里插入图片描述

2. 实验环境

  • 第一步,在ssm_mybatis项目下建mybatis-chap03-sql模块
  • 第二步,导入mybatis、mysql、junit包
    目录结构与导包参考Mybatis案例
  • 第三步,创建数据库mybatis,建表t_customer。建表语句如下:
USE mybatis;CREATE TABLE t_customer (id int(32) PRIMARY KEY AUTO_INCREMENT,username varchar(50),jobs varchar(50),phone varchar(16));INSERT INTO t_customer VALUES ('1', 'joy', 'teacher', '13733333333');INSERT INTO t_customer VALUES ('2', 'jack', 'teacher', '13522222222');INSERT INTO t_customer VALUES ('3', 'tom', 'worker', '15111111111');
  • 第四步,创建POJO类Customer,各字段与表t_customer字段一致(放pojo包中)
package com.cshbxy.pojo;public class Customer {private int id;private String username;private String jobs;private String phone;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getJobs() {return jobs;}public void setJobs(String jobs) {this.jobs = jobs;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Overridepublic String toString() {return "Customer{" +"id=" + id +", username='" + username + '\'' +", jobs='" + jobs + '\'' +", phone='" + phone + '\'' +'}';}}
  • 第五步,创建Mapper接口CustomerMapper,对需要的操作进行定义(放mapper包)
package com.cshbxy.mapper;import com.cshbxy.pojo.Customer;import java.util.List;import java.util.Map;public interface CustomerMapper {/*完成if元素实验。实验要求:按姓名和职业查询,如果查询值为空或空串,则不纳入条件*/List<Customer> selectByNameAndJobs_if(Customer customer);/*完成choose when otherwise元素实验。实验要求:仅按姓名或职业中的某个给定条件查询(查询值为空或空串,不纳入条件),如果姓名、职业均未给定查询值,则查询手机号非空用户*/List<Customer> selectByNameOrJobs_choose(Customer customer);/*完成where实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件*/List<Customer> selectByNameAndJobs_where(Customer customer);/*完成trim实验。实验要求:按姓名或职业查询,如果查询值为空或空串,则不纳入条件*/List<Customer> selectByNameAndJobs_trim(Customer customer);/*完成set实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段*/int updateById_set(Customer customer);/*完成trim实验。实验要求:按id更新记录,只修改给定属性值不为空和空串的字段*/int updateById_trim(Customer customer);/*完成foreach遍历数组实验。实验要求:查询id值为多个指定值的记录。多个id值通过数组传入*/List<Customer> selectById_Arrays(int[] ids);/*完成foreach遍历数组实验。实验要求:查询id值为多个指定值的记录。多个id值通过List传入*/List<Customer> selectById_List(List<Integer> ids);/*完成foreach遍历Map实验。实验要求:仅显示id值为数组元素值的记录。多个id值通过Map传入*/List<Customer> selectById_Map(Map ids);/*完成参数为Map的实验。实验要求:查询记录,查询字段及值由Map给定(即:查询条件有不确定性,由用户给出)。 - 此种情况下,Map传入多参数时要求用户调用给定实参时,实参的键值必须是表字段名,否则会出错。*/List<Customer> selectByUnConditon(Map customer);}
  • 第六步,为上述接口创建映射文件CustomerMapper.xml(放resources的mapper文件夹下),实

现各方法的sql映射在后续示例中给出。注意两个问题: 映射文件命名空间namespace为上述接口的全限定名
com.lyrpx.mapper.CustomerMapper
为了方便,类的名称均采用包扫描默认别名,后续记得在核心配置文件中进行包扫描别名配置
一般情况下,写完一个测试一个。所以,可以写完第一个映射语句就去配置核心配置文件,之后测试!

<mapper namespace="com.lyrpx.mapper.CustomerMapper"></mapper>
  • 第七步,创建Mybatis核心配置文件mybatis-config.xml(放resources文件夹)
<configuration><properties resource="db.properties"/><typeAliases><package name="com.cshbxy.pojo"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${mysql.driver}"/><property name="url" value="${mysql.url}"/><property name="username" value="${mysql.username}"/><property name="password" value="${mysql.password}"/></dataSource></environment></environments><mappers><mapper resource="mapper/CustomerMapper.xml"/></mappers></configuration>
  • 第八步,编写测试类TestCustomerMapper(放test\java文件夹),此处给模板,后续自己按模板
    添加单元测试
  • 模板一:创建会话对象时,没有带参数
import com.cshbxy.mapper.CustomerMapper;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.IOException;import java.io.InputStream;public class TestCustomerMapper {@Testpublic void testIf() throws IOException {//第一大步,创建会话对象sqlSessionInputStream in = Resources.getResourceAsStream("mybatisconfig.xml");SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession=factory.openSession();//第二大步,通过会话对象的getMapper()方法实现接口CustomerMapper,并获取该对象CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);//第三大步,完成测试(此处自己针对实现的方法进行测试)/*第四大步,关闭会话对象。如果是增、删、修改操作,关闭之前还要提交事务。语句如下:sqlSession.commit();*/sqlSession.close();}}
  • 模板二:创建会话对象时,带true参数
import com.cshbxy.mapper.CustomerMapper;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.IOException;import java.io.InputStream;public class TestCustomerMapper {@Testpublic void testIf() throws IOException {//第一大步,创建会话对象sqlSessionInputStream in = Resources.getResourceAsStream("mybatisconfig.xml");SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);SqlSession sqlSession=factory.openSession(true); //true:关闭时自动提交事务//第二大步,通过会话对象的getMapper()方法实现接口CustomerMapper,并获取该对象CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);//第三大步,完成测试(此处自己针对实现的方法进行测试)//第四大步,关闭会话对象。因为之前创建事务时带true参数,所以此处不必考虑事务提交问题sqlSession.close();}}

二、条件查询操作

1.if元素

  • 作用:用于单条件判断,条件满足时拼装其内部SQL代码。该元素经常与其它元素联合使用。
  • 注意事项:
  • if前面要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
<select id="selectByNameAndJobs_if" resultType="customer">select * from mybatis.t_customer where 1=1/*分析:if元素,条件满足时才拼装SQL语句*/<if test="username!=null and username!=''">and username=#{username}</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></select>

2.choose、when、otherwise元素

  • 作用:用于多分支条件判断,只拼装首个满足条件的when内部SQL代码,均不满足则拼装otherwise内部SQL代码。
  • 注意事项:
  • if前面要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • 只会执行一个条件语句,或均不执行
  • otherwise可以不写
<select id="selectByNameOrJobs_choose" resultType="customer">select * from mybatis.t_customer where 1=1/*分析:choose元素仅拼装第一个满足条件的SQL语句*/<choose><when test="username!=null and username!=''">and username = #{username}</when><when test="jobs!=null and jobs!=''">and jobs = #{jobs}</when><otherwise>and phone is not null</otherwise></choose></select>

3.where、trim元素

(1)where元素

  • 作用:自动判断是否加where关键字,或去除不必要的逻辑运算符。
  • 注意事项:
  • 不要写where 1=1
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • where内部要写条件拼装语句
<select id="selectByNameAndJobs_where" resultType="customer">select * from mybatis.t_customer/*分析:where元素会根据内部的拼装语句自动判断是否加where,及是否去除and*/<where><if test="username!=null and username!=''">and username=#{username}</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></where></select>

(2)trim元素

  • 常用属性
    在这里插入图片描述
  • 作用
  • 自动判断是否在拼装语句的最前面加prefix属性给定的前缀值,去除prefixOverrides属性给定 的前缀字符串;
  • 自动判断是否在拼装语句的最后面加suffix 属性给定的后缀值,去除suffixOverrides属性给定的后缀字符串。
  • 注意事项:
  • 引用传入参数值语法:#{属性名},属性名必须与传入参数类定义中的一致
  • trim内部要写条件拼装语句
  • 要加入的前缀、后缀,及要去除的前缀、后缀值不要赋错了属性
<select id="selectByNameAndJobs_trim" resultType="customer">select * from mybatis.t_customer/*分析:trim元素会根据内部的拼装语句自动判断是否加前缀where,及是否去除前缀and*/<trim prefix="where" prefixOverrides="and"><if test="username!=null and username!=''">and username=#{username}</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></trim></select>

三、更新操作

1.set元素实现

作用:自动判断是否加set关键字,是否去除逗号。

<update id="updateById_set">update mybatis.t_customer/*分析:set元素自动判断是否加set关键字,是否去除逗号*/<set><if test="username!=null and username!=''">username=#{username},</if><if test="jobs!=null and jobs!=''">jobs=#{jobs},</if><if test="phone!=null and phone!=''">phone=#{phone},</if></set>where id=#{id}</update>

2.trim元素实现

trim也可以实现更新操作,具体用法见前述。

<update id="updateById_trim">update mybatis.t_customer/*分析:trim元素自动判断是否加前缀set,是否去除后缀字符串逗号*/<trim prefix="set" suffixOverrides=","><if test="username!=null and username!=''">username=#{username},</if><if test="jobs!=null and jobs!=''">jobs=#{jobs},</if><if test="phone!=null and phone!=''">phone=#{phone},</if></trim>where id=#{id}</update>

测试代码

public class TestCustomerMapper {    @Test    public void testIf() throws IOException {//获取会话对象sqlSession SqlSession sqlSession= MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);//完成测试(此处自己针对实现的方法进行测试) Customer cc=new Customer(); cc.setJobs("teacher"); List<Customer> customers=mapper.selectByNameAndJobs_if(cc); for (Customer customer : customers){     System.out.println(customer); } sqlSession.close();    }    @Test    public void testChoose(){ SqlSession sqlSession = MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class); Customer customer=new Customer(); customer.setUsername("tom"); customer.setJobs("teacher"); List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer); for (Customer customer1 : customers) {     System.out.println(customer1); } //关闭会话 sqlSession.close();    }    @Test    public void TestWhere(){ SqlSession sqlSession = MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class); Customer customer=new Customer(); customer.setUsername("jack"); customer.setJobs("teacher"); List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer); for (Customer customer2 : customers) {     System.out.println(customer2); } //关闭会话 sqlSession.close();    }    @Test    public void TestTrim(){ SqlSession sqlSession = MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class); Customer customer=new Customer(); customer.setUsername("jack"); customer.setJobs("teacher"); List<Customer> customers= sqlSession.selectList("com.lyrpx.mapper.CustomerMapper.selectByNameOrJobs_choose",customer); for (Customer customer3 : customers) {     System.out.println(customer3); } //关闭会话 sqlSession.close();    }    @Test    public void TestSet(){ SqlSession sqlSession = MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class); Customer customer=new Customer(); customer.setId(3); customer.setPhone("13142123762"); int rows=sqlSession.update("com.lyrpx.mapper.CustomerMapper.updateById_set",customer); if (rows>0){     System.out.println("您修改了"+rows+"条数据"); }else {     System.out.println("执行修改操作失败!"); } sqlSession.commit(); sqlSession.close();    }    @Test    public void TestUpdateTrim(){ SqlSession sqlSession = MyTool.getSqlSession(); CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class); Customer customer=new Customer(); customer.setId(3); customer.setPhone("10086"); int rows=sqlSession.update("com.lyrpx.mapper.CustomerMapper.updateById_set",customer); if (rows>0){     System.out.println("您修改了"+rows+"条数据"); }else {     System.out.println("执行修改操作失败!"); } sqlSession.commit(); sqlSession.close();    }}

四、复杂查询操作

1.foreach元素及其属性

  • 作用:用于遍历传入的集合类型参数数据。(迭代就是遍历的意思)
  • 常用属性
    在这里插入图片描述

2.foreach元素迭代数组

  • 注意事项:

collection的默认属性值为array;
同样可以使用@Param注解自定义keyName;

3.foreach元素迭代List

  • 注意事项:

collection的默认属性值为list,同样可以使用@Param注解自定义keyName;

4.foreach元素迭代Map

  • 注意事项:

collection的属性值可为三种情況:
1.遍历map.keys;
2.遍历map.values;
3.遍历map.entry

五、案例:学生信息查询系统

在这里插入图片描述
数据表生成代码如下:

DROP TABLE IF EXISTS `dm_student`;CREATE TABLE `dm_student` (`id` int(32) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`major` varchar(50) DEFAULT NULL,`sno` varchar(16) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;-- ------------------------------ Records of dm_student-- ----------------------------INSERT INTO `dm_student` VALUES ('1', '张三', '数学', '10001');INSERT INTO `dm_student` VALUES ('2', '李四', '英语', '10002');INSERT INTO `dm_student` VALUES ('3', '王五', '计算机', '10003');INSERT INTO `dm_student` VALUES ('4', '王刚', '化学', '10004');INSERT INTO `dm_student` VALUES ('5', '李华', '物理', '10005');INSERT INTO `dm_student` VALUES ('6', '李雷', '中文', '10006');INSERT INTO `dm_student` VALUES ('7', '张飞', '英语', '10007');INSERT INTO `dm_student` VALUES ('9', '刘小小', '地理', '10001');

1.该系统要求实现以下功能
(1)单条件查询:按id查询学生信息。(方法名:findById)
(2)多条件查询(方法名:findStudentByNameOrMajor)
当用户输入的学生姓名不为空,则只根据学生姓名进行学生信息的查询;
当用户输入的学生姓名为空,而学生专业不为空,则只根据学生专业进行学生的查询;
(3)foreach遍历查询:按用户给定的多个专业查询学生信息。用如下三种方法完成:
多个专业值放在一个数组中传入。(方法名:findByMajor_Arrays)
多个专业值放在一个List中传入。(方法名:findByMajor_List)
多个专业值放在一个Map中传入。(方法名:findByMajor_Map)
(4)按id值修改学生信息,条件及修改的值用一个对象传入。(方法名:updateById)
2.完成如下测试

  • (1)测试查询出所有id值小于5的学生的信息。
  • (2)查询出数学、英语、计算机专业的学生信息。
  • (3)查询出有所专业值非空的学生信息。
  • (4)修改id值为2的学生专业为数学

案例整理完上传!