• Java框架 MyBatis动态SQL


            Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了 解决 拼接SQL语句字符串时的痛点问题。

    0、准备工作

    1、引入依赖

    1. <dependencies>
    2.         
    3.         <dependency>
    4.             <groupId>org.mybatisgroupId>
    5.             <artifactId>mybatisartifactId>
    6.             <version>3.5.7version>
    7.         dependency>
    8.  
    9.         
    10.         <dependency>
    11.             <groupId>junitgroupId>
    12.             <artifactId>junitartifactId>
    13.             <version>4.12version>
    14.             <scope>testscope>
    15.         dependency>
    16.  
    17.         
    18.         <dependency>
    19.             <groupId>mysqlgroupId>
    20.             <artifactId>mysql-connector-javaartifactId>
    21.             <version>8.0.27version>
    22.         dependency>
    23.  
    24.         
    25.         <dependency>
    26.             <groupId>log4jgroupId>
    27.             <artifactId>log4jartifactId>
    28.             <version>1.2.17version>
    29.         dependency>
    30.     dependencies>

    2、数据表数据

    1. CREATE TABLE t_dept(
    2.     dept_id INT PRIMARY KEY AUTO_INCREMENT,
    3.     dept_name VARCHAR(20)
    4. );
    5.  
    6. CREATE TABLE t_emp(
    7.     emp_id INT PRIMARY KEY AUTO_INCREMENT,
    8.     emp_name VARCHAR(20),
    9.     age INT,
    10.     gender CHAR,
    11.     dept_id INT
    12. );
    13.  
    14. INSERT INTO t_dept(dept_name) VALUES ('A'),('B'),('C');
    15.  
    16. INSERT INTO t_emp(emp_name,age,gender,dept_id) VALUES
    17. ('张三',20,'女',1),
    18. ('李四',22,'女',2),
    19. ('王五',21,'男',3),
    20. ('赵六',23,'男',1),
    21. ('田七',21,'女',3);

    3、创建与数据表相对应 java 实体类

    1. public class Emp {
    2.     private Integer empId;
    3.     private String empName;
    4.     private Integer age;
    5.     private String gender;
    6.     private Integer deptId;
    7.  
    8.     public Emp() {
    9.     }
    10.  
    11.     public Emp(Integer empId, String empName, Integer age, String gender, Integer deptId) {
    12.         this.empId = empId;
    13.         this.empName = empName;
    14.         this.age = age;
    15.         this.gender = gender;
    16.         this.deptId = deptId;
    17.     }
    18.  
    19.     public Integer getEmpId() {
    20.         return empId;
    21.     }
    22.  
    23.     public void setEmpId(Integer empId) {
    24.         this.empId = empId;
    25.     }
    26.  
    27.     public String getEmpName() {
    28.         return empName;
    29.     }
    30.  
    31.     public void setEmpName(String empName) {
    32.         this.empName = empName;
    33.     }
    34.  
    35.     public Integer getAge() {
    36.         return age;
    37.     }
    38.  
    39.     public void setAge(Integer age) {
    40.         this.age = age;
    41.     }
    42.  
    43.     public String getGender() {
    44.         return gender;
    45.     }
    46.  
    47.     public void setGender(String gender) {
    48.         this.gender = gender;
    49.     }
    50.  
    51.     public Integer getDeptId() {
    52.         return deptId;
    53.     }
    54.  
    55.     public void setDeptId(Integer deptId) {
    56.         this.deptId = deptId;
    57.     }
    58.  
    59.     @Override
    60.     public String toString() {
    61.         return "Emp{" +
    62.                 "empId=" + empId +
    63.                 ", empName='" + empName + '\'' +
    64.                 ", age=" + age +
    65.                 ", gender='" + gender + '\'' +
    66.                 ", deptId=" + deptId +
    67.                 '}';
    68.     }
    69. }
    1. public class Dept {
    2.     private Integer deptId;
    3.     private String deptName;
    4.  
    5.     public Dept(Integer deptId, String deptName) {
    6.         this.deptId = deptId;
    7.         this.deptName = deptName;
    8.     }
    9.  
    10.     public Dept() {
    11.     }
    12.  
    13.     public Integer getDeptId() {
    14.         return deptId;
    15.     }
    16.  
    17.     public void setDeptId(Integer deptId) {
    18.         this.deptId = deptId;
    19.     }
    20.  
    21.     public String getDeptName() {
    22.         return deptName;
    23.     }
    24.  
    25.     public void setDeptName(String deptName) {
    26.         this.deptName = deptName;
    27.     }
    28.  
    29.     @Override
    30.     public String toString() {
    31.         return "Dept{" +
    32.                 "deptId=" + deptId +
    33.                 ", deptName='" + deptName + '\'' +
    34.                 '}';
    35.     }
    36. }

    4、jdbc.properties 文件

    1. jdbc.driver=com.mysql.cj.jdbc.Driver
    2. jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
    3. jdbc.username=root
    4. jdbc.password=root


    5、MyBaits 核心配置文件

    1. configuration
    2.         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    3.         "http://mybatis.org/dtd/mybatis-3-config.dtd">
    4. <configuration>
    5.     
    6.  
    7.     
    8.     <properties resource="jdbc.properties"/>
    9.  
    10.     <typeAliases>
    11.         <package name="com.chenyixin.ssm.pojo"/>
    12.     typeAliases>
    13.  
    14.     
    15.     <environments default="development">
    16.         <environment id="development">
    17.             <transactionManager type="JDBC"/>
    18.             <dataSource type="POOLED">
    19.                 <property name="driver" value="${jdbc.driver}"/>
    20.                 <property name="url" value="${jdbc.url}"/>
    21.                 <property name="username" value="${jdbc.username}"/>
    22.                 <property name="password" value="${jdbc.password}"/>
    23.             dataSource>
    24.         environment>
    25.  
    26.     environments>
    27.  
    28.     
    29.     <mappers>
    30.         
    31.         <package name="com.chenyixin.ssm.mapper"/>
    32.     mappers>
    33. configuration>

    6、工具类:

    1. package com.chenyin.ssm.utils;
    2.  
    3. import org.apache.ibatis.io.Resources;
    4. import org.apache.ibatis.session.SqlSession;
    5. import org.apache.ibatis.session.SqlSessionFactory;
    6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    7.  
    8. import java.io.InputStream;
    9.  
    10. public class SqlSessionUtil {
    11.  
    12.     public static SqlSession getSqlSession() {
    13.         try {
    14.             // 获取核心的配置文件
    15.             InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    16.             // 创建 SqlSessionFactoryBuilder 对象
    17.             SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    18.  
    19.             // 通过核心配置文件多对应的字节输入流创建工厂类 SqlSessionFactory ,生产 SqlSession 对象
    20.             SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
    21.  
    22.             // 创建 SqlSession 对象(自动操作事务)
    23.             return sqlSessionFactory.openSession(true);
    24.         } catch (Exception e) {
    25.             throw new RuntimeException(e);
    26.         }
    27.  
    28.     }
    29. }

    7、log4j.xml配置文件

    1. log4j:configuration SYSTEM "log4j.dtd">
    2.  
    3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    4.  
    5.     <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
    6.         <param name="Encoding" value="UTF-8" />
    7.         <layout class="org.apache.log4j.PatternLayout">
    8.             <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n" />
    9.         layout>
    10.     appender>
    11.     <logger name="java.sql">
    12.         <level value="debug" />
    13.     logger>
    14.     <logger name="org.apache.ibatis">
    15.         <level value="info" />
    16.     logger>
    17.     <root>
    18.         <level value="debug" />
    19.         <appender-ref ref="STDOUT" />
    20.     root>
    21. log4j:configuration>

    1、if 标签

     if标签可通过 test 属性的表达式进行判断,若表达式的结果为 true,则标签中的内容会执行;反之 标签中的内容不会执行

    DynamicMapper.xml 配置文件:

    1. <select id="getEmpByCondition" resultType="emp">
    2. select * from t_emp where 1 = 1
    3. <if test="empName != null and empName != ''">
    4. and emp_name = #{empName}
    5. if>
    6. <if test="age != null and age != ''">
    7. and age = #{age}
    8. if>
    9. <if test="gender != null and gender != ''">
    10. and gender = #{gender}
    11. if>
    12. select>

    测试类:

    1. public class DynamicMapperTest {
    2. SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    3. DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class);
    4. @Test
    5. public void getEmpByCondition() {
    6. Emp emp1 = new Emp(null,"张三",20,"女");
    7. List empList1 = mapper.getEmpByCondition(emp1);
    8. empList1.forEach(System.out::println);
    9. // Emp{empId=1, empName='张三', age=20, gender='女', dept=null}
    10. Emp emp2 = new Emp(null,null,null,"男");
    11. List empList2 = mapper.getEmpByCondition(emp2);
    12. empList2.forEach(System.out::println);
    13. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    14. // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}
    15. }
    16. }

    2、where 标签

    where和if一般结合使用:
            a> 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
            b> 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的 and去掉
             注意:where标签不能去掉条件最后多余的and

    DynamicMapper.xml 配置文件:

    1. <select id="getEmpByCondition2" resultType="emp">
    2. select * from t_emp
    3. <where>
    4. <if test="empName != null and empName != ''">
    5. emp_name = #{empName}
    6. if>
    7. <if test="age != null and age != ''">
    8. and age = #{age}
    9. if>
    10. <if test="gender != null and gender != ''">
    11. and gender = #{gender}
    12. if>
    13. where>
    14. select>

    测试:

    1. @Test
    2. public void getEmpByCondition2() {
    3. Emp emp1 = new Emp(null,"张三",20,"女");
    4. List empList1 = mapper.getEmpByCondition2(emp1);
    5. System.out.println(empList1);
    6. // [Emp{empId=1, empName='张三', age=20, gender='女', dept=null}]
    7. Emp emp2 = new Emp(null,"",null,"女");
    8. List empList2 = mapper.getEmpByCondition2(emp2);
    9. empList2.forEach(System.out::println);
    10. // Emp{empId=1, empName='张三', age=20, gender='女', dept=null}
    11. // Emp{empId=2, empName='李四', age=22, gender='女', dept=null}
    12. // Emp{empId=5, empName='田七', age=21, gender='女', dept=null}
    13. Emp emp3 = new Emp(null,"",null,"");
    14. List empList3 = mapper.getEmpByCondition2(emp3);
    15. empList3.forEach(System.out::println);
    16. // Emp{empId=1, empName='张三', age=20, gender='女', dept=null}
    17. // Emp{empId=2, empName='李四', age=22, gender='女', dept=null}
    18. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    19. // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}
    20. // Emp{empId=5, empName='田七', age=21, gender='女', dept=null}
    21. }

    3、trim 标签

    trim用于去掉或添加标签中的内容
    常用属性:
             prefix :在trim标签中的内容的前面添加某些内容
             prefixOverrides :在trim标签中的内容的前面去掉某些内容
             suffix :在trim标签中的内容的后面添加某些内容
             suffixOverrides :在trim标签中的内容的后面去掉某些内容

    DynamicMapper.xml 配置文件:

    1. <select id="getEmpByCondition3" resultType="emp">
    2. select * from t_emp
    3. <trim prefix="where" suffixOverrides="and">
    4. <if test="empName != null and empName != ''">
    5. emp_name = #{empName} and
    6. if>
    7. <if test="age != null and age != ''">
    8. age = #{age} and
    9. if>
    10. <if test="gender != null and gender != ''">
    11. gender = #{gender}
    12. if>
    13. trim>
    14. select>

    测试:

    1. @Test
    2. public void getEmpByCondition3() {
    3. Emp emp1 = new Emp(null,"张三",20,"女");
    4. List empList1 = mapper.getEmpByCondition3(emp1);
    5. System.out.println(empList1);
    6. // Emp{empId=1, empName='张三', age=20, gender='女', dept=null}
    7. Emp emp2 = new Emp(null,"",null,"男");
    8. List empList2 = mapper.getEmpByCondition3(emp2);
    9. empList2.forEach(System.out::println);
    10. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    11. // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}
    12. Emp emp3 = new Emp(null,"",null,"");
    13. List empList3 = mapper.getEmpByCondition3(emp3);
    14. empList3.forEach(System.out::println);
    15. // Emp{empId=1, empName='张三', age=20, gender='女', dept=null}
    16. // Emp{empId=2, empName='李四', age=22, gender='女', dept=null}
    17. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    18. // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}
    19. // Emp{empId=5, empName='田七', age=21, gender='女', dept=null}
    20. }

    4、choose、when、otherwise

    choose、when、otherwise 组合标签

            相当于 java 中的 if...else if ...else

            when 至少设置一个, otherwise 至多设置一个

    DynamicMapper.xml 配置文件:

    1. <select id="getEmpByChoose" resultType="emp">
    2. select * from t_emp
    3. <where>
    4. <choose>
    5. <when test="empName != null and empName != ''">
    6. emp_name = #{empName}
    7. when>
    8. <when test="age != null and age != ''">
    9. age = #{age}
    10. when>
    11. <when test="gender != null and gender != ''">
    12. gender = #{gender}
    13. when>
    14. choose>
    15. where>
    16. select>

    测试:

    1. @Test
    2. public void getEmpByChoose() {
    3. Emp emp1 = new Emp(null,"李四",20,"女");
    4. List empList1 = mapper.getEmpByChoose(emp1);
    5. empList1.forEach(System.out::println);
    6. // [Emp{empId=2, empName='李四', age=22, gender='女', dept=null}]
    7. Emp emp2 = new Emp(null,"",21,"男");
    8. List empList2 = mapper.getEmpByChoose(emp2);
    9. empList2.forEach(System.out::println);
    10. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    11. // Emp{empId=5, empName='田七', age=21, gender='女', dept=null}
    12. Emp emp3 = new Emp(null,"",null,"男");
    13. List empList3 = mapper.getEmpByChoose(emp3);
    14. empList3.forEach(System.out::println);
    15. // Emp{empId=3, empName='王五', age=21, gender='男', dept=null}
    16. // Emp{empId=4, empName='赵六', age=23, gender='男', dept=null}
    17. }

    5、foreach 标签

    foreach 标签

    属性

            collection:设置要循环的数组或集合

            item:用一个字符串表示数组或集合中的每一个数据

            separator:设置每次循环的数据之间的分隔符(所设置的分割符默认左右都有一个空格)

            open:循环的所有内容以什么开始

            close:循环的所有内容以什么结束

            index:循环的索引

    5.1、 使用 foreach 标签 实现批量添加

    DynamicMapper.xml 配置文件:

    1. <insert id="insertMoreEmp" >
    2. insert into t_emp values
    3. <foreach collection="emps" item="emp" separator=",">
    4. (null,#{emp.empName},#{emp.age},#{emp.gender},null)
    5. foreach>
    6. insert>

    测试:

    1. @Test
    2. public void insertMoreEmp() {
    3. Emp emp1 = new Emp(null, "小明", 20, "男");
    4. Emp emp2 = new Emp(null, "小芳", 19, "女");
    5. Emp emp3 = new Emp(null, "李华", 22, "女");
    6. Emp emp4 = new Emp(null, "小华", 20, "女");
    7. Emp emp5 = new Emp(null, "小王", 21, "男");
    8. Emp emp6 = new Emp(null, "老王", 32, "男");
    9. Emp emp7 = new Emp(null, "老华", 33, "男");
    10. List emps = Arrays.asList(emp1, emp2, emp3,emp4,emp5,emp6,emp7);
    11. int i = mapper.insertMoreEmp(emps);
    12. System.out.println(i); // 7
    13. }

     

    5.2、使用 foreach 标签 实现批量删除

    ① 方式1

    DynamicMapper.xml 配置文件:

    1. <delete id="deleteMoreEmp1">
    2. delete from t_emp where emp_id in
    3. (
    4. <foreach collection="empIds" item="empId" separator=",">
    5. #{empId}
    6. foreach>
    7. );
    8. delete>

    测试:

    1. @Test
    2. public void deleteMoreEmp1() {
    3. Integer[] empIds = new Integer[]{7,9};
    4. int i = mapper.deleteMoreEmp1(empIds);
    5. System.out.println(i); // 2
    6. }

    结果:

    ② 方式2

    DynamicMapper.xml 配置文件:

    1. <delete id="deleteMoreEmp2">
    2. delete from t_emp where emp_id in
    3. <foreach collection="empIds" item="empId" separator="," open="(" close=")">
    4. #{empId}
    5. foreach>
    6. delete>

    测试:

    1. @Test
    2. public void deleteMoreEmp2() {
    3. Integer[] empIds = new Integer[]{6,10,11};
    4. int i = mapper.deleteMoreEmp2(empIds);
    5. System.out.println(i); // 3
    6. }

    结果:

    ③ 方式3

    DynamicMapper.xml 配置文件:

    1. <delete id="deleteMoreEmp3">
    2. delete from t_emp where
    3. <foreach collection="empIds" item="empId" separator="or">
    4. emp_id = #{empId}
    5. foreach>
    6. delete>

    测试:

    1. @Test
    2. public void deleteMoreEmp3() {
    3. Integer[] empIds = new Integer[]{8,12};
    4. int i = mapper.deleteMoreEmp3(empIds);
    5. System.out.println(i); // 2
    6. }

    结果:

     

    6、sql 标签

    sql 标签

            可以记录一段 sql ,在需要的地方使用 include 标签进行引用

    DynamicMapper.xml 配置文件:

    1. <sql id="empColumns">
    2. emp_id,emp_name,age,gender
    3. sql>
    4. <select id="selectAll" resultType="emp">
    5. select <include refid="empColumns"/> from t_emp;
    6. select>

    测试:

    1. @Test
    2. public void selectAll() {
    3. List emps = mapper.selectAll();
    4. emps.forEach(System.out::println);
    5. }

    结果:

     

  • 相关阅读:
    2020年大厂Java面试前复习的正确姿势(800+面试题答案解析)
    java计算机毕业设计ssm+vue青年志愿者社团管理系统
    Linux Zabbix企业级监控平台+cpolar实现远程访问
    笔记1.1 计算机网络基本概念
    java计算机毕业设计医院远程诊断系统源代码+系统+数据库+lw文档
    torchscript相关知识介绍(二)
    学习react 笔记一
    读像火箭科学家一样思考笔记05_思想实验
    解决wget下载过慢的问题
    在微信小程序上怎么实现多门店管理功能
  • 原文地址:https://blog.csdn.net/weixin_65637841/article/details/126319265