草庐IT

学习笔记——Mybatis动态SQL

isDaHua 2023-04-17 原文

2023-01-12

一、Mybatis动态SQL

即将SQL动态化

同时Mybatis的动态SQL支持OFNL表达式,OGNL(Object Graph Navigation Language)对象图导航语言。

1、先搭建环境

(1)创建一个“maven”模块,命名为“day04_mybatis”

(2)在“day04_mybatis”中的“pom.xml”中的<project>标签内部添加依赖,即添加jar包

<dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>


    </dependencies>

(3)在"day04_mybatis.src.main.resources"中添加"db.properties(连接数据库,里面的形式是:key=value),需要设置4个值(driver、url、username、password)"和“log4j.xml”

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
        </layout>
    </appender>

    <logger name="java.sql">
        <level value="debug"/>
    </logger>

    <logger name="org.apache.ibatis">
        <level value="info"/>
    </logger>

    <root>
        <level value="debug" />
        <appender-ref ref="STDOUT" />
    </root>

</log4j:configuration>

(4)在“day04_mybatis.src.resources”中添加“mybatis-config.xml”

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--    设置属性-->
    <properties resource="db.properties"></properties>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--        延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--        延迟加载的属性-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

    <typeAliases>
        <package name="com.hh.mybatis.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${db.driver}"/>
                <property name="url" value="${db.url}"/>
                <property name="username" value="${db.username}"/>
                <property name="password" value="${db.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/EmployeeMapper.xml"></mapper>
    </mappers>
</configuration>

(5)在“day04_mybatis.src.main.java”中创建“com.hh.mybatis.pojo”和“com.hh.mybatis.mapper”。之后在“day04_mybatis.src.main.resources”中创建“mapper”文件夹,在“mapper”文件夹下创建“EmployeeMapper.xml”

(6)在“pojo”文件夹下创建“Dept”、“Employee”。在“mapper”文件夹下创建“EmployeeMapper”接口并添加代码

public interface EmployeeMapper {
    /**
     * 按条件查询员工信息(条件不确定)
     * @return
     */
    public List<Employee> selectEmpByOpr(Employee employee);
}

(7)EmployeeMapper.xml中的映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hh.mybatis.mapper.EmployeeMapper" >
<!-- 按条件查询员工信息(条件不确定)-->
    <select id="selectEmpByOpr" resultType="employee">
        select
            id,
            last_name,
            email,
            salary,
            dept_id,
        from
            tbl_employee
    </select>
</mapper>

(8)在“day04_mybatis.src.test.java"中创建测试类“TestDynamicSql”

public class TestDynamicSql {
    @Test
    public void testDynamicSql() throws Exception{
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        Employee employee = new Employee();
        List<Employee> employees = employeeMapper.selectEmpByOpr(employee);
        for (Employee employee1 : employees) {
            System.out.println("employee1 = " + employee1);
        }
    }
}

(9)注意:

如果出现“java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corres”这种问题报错时,可以将sql语句先在“SQLyog”中先写一遍,运行,如果运行无误,之后将代码再放入“映射文件”中,即可

2、进行动态SQL设置

(1)注意:在动态SQL中“test”中放置的是“属性”

(2)动态SQL<if>标签

用于完成简单的判断

<select id="selectEmpByOpr" resultType="employee">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
        WHERE
            <if test="id != null">
                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 salary = #{salary}
            </if>
    </select>

测试类

public class TestDynamicSql {
    @Test
    public void testDynamicSql() throws Exception{
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        Employee employee = new Employee();
        //动态标签
        employee.setId(1);
//        employee.setSalary(50.0);
        List<Employee> employees = employeeMapper.selectEmpByOpr(employee);
        for (Employee employee1 : employees) {
            System.out.println("employee1 = " + employee1);
        }
    }
}

注意:动态参数中<if>,无参数时报错,没有第一个参数也报错。

(3)动态SQL:<where>标签

where用于解决SQL语句中where关键字以及条件前面的and或者or的问题

<select id="selectEmpByOpr" resultType="employee">
        SELECT
            id,
            last_name,
            email,
            salary
        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 salary = #{salary}
            </if>
        </where>
    </select>

(3)动态SQL:<trim>

可以在条件判断完的SQL语句前后添加或者去掉指定的字符

标签中的属性:

①prefix:添加前缀

②prefixOverrides:去掉前缀

③suffix:添加后缀

④suffixOverrides:去掉后缀

例如:

    <select id="selectEmpByOprTrim" resultType="employee">
         SELECT
            id,
            last_name,
            email,
            salary
        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}
            </if>
        </trim>
    </select>

(4)动态SQL:<set>

用于解决修改操作中SQL语句中可能多出逗号的问题

在“EmployeeMapper”接口中添加方法

/**
     * 按条件修改员工信息(条件不确定)
     * @param employee
     */
    public void updateEmpByOpr(Employee employee);

映射文件

<update id="updateEmpByOpr">
        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>

(5)动态SQL标签:<choose>

类似于java中if-else(switch-case)结构

    <update id="updateEmpByOneOpr">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
        <where>
             <choose>
                 <when test="id != null">
                     id = #{id}
                 </when>
                 <when test="email != null">
                     email = #{email}
                 </when>
                 <when test="salary != null">
                     salary = #{salary}
                 </when>
                 <otherwise>
                     1=1
                 </otherwise>
             </choose>
        </where>
    </update>

(6)动态SQL标签:<foreach>

类似于java中的for循环

collection:要迭代的集合

item:当前从集合中迭代出的元素

separator:元素与元素之间的分隔符

①“EmployeeMapper”接口中的函数

/**
     * 通过多个id获取员工信息
     * @param ids
     * @return
     */
    public List<Employee> selectEmpByIds(@Param("ids") List<Integer> ids);

②映射文件

<select id="selectEmpByIds" resultType="employee">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
        <where>
            id in
            (
            <foreach collection="ids" item="id" separator=",">
                #{id}
            </foreach>
            )
        </where>
    </select>

 ③测试主要代码

List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(3);
        ids.add(4);
        List<Employee> employees = employeeMapper.selectEmpByIds(ids);
        for (Employee employee1 : employees) {
            System.out.println("employee1 = " + employee1);
        }

(7)sql标签

提取可重用SQL片段

    <sql id="select_employee">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
    </sql>
    
    <sql id="emp_col">
        id,
        last_name,
        email,
        salary
    </sql>
<!-- 按条件查询员工信息(条件不确定)-->
    <select id="selectEmpByOpr" resultType="employee">
        select
            <include refid="emp_col"></include>
        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 salary = #{salary}
            </if>
        </where>
    </select>

 

有关学习笔记——Mybatis动态SQL的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  3. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  4. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  5. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  6. ruby - 在 Ruby 中动态创建数组 - 2

    有没有办法在Ruby中动态创建数组?例如,假设我想遍历用户输入的书籍数组:books=gets.chomp用户输入:"TheGreatGatsby,CrimeandPunishment,Dracula,Fahrenheit451,PrideandPrejudice,SenseandSensibility,Slaughterhouse-Five,TheAdventuresofHuckleberryFinn"我把它变成一个数组:books_array=books.split(",")现在,对于用户输入的每一本书,我想用Ruby创建一个数组。伪代码来做到这一点:x=0books_array.

  7. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  8. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  9. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

  10. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

随机推荐