Mybatis进阶(动态SQL)

news2024/11/18 21:41:37

文章目录

    • 1.动态SQL
        • 1.基本介绍
          • 1.为什么需要动态SQL
          • 2.基本说明
          • 3.动态SQL常用标签
        • 2.环境搭建
          • 1.新建子模块
          • 2.删除不必要的两个文件夹
          • 3.创建基本结构
          • 4.父模块的pom.xml
          • 5.jdbc.properties
          • 6.mybatis-config.xml
          • 7.MyBatisUtils.java
          • 8.MonsterMapper.java
          • 9.MonsterMapper.xml
          • 10.测试MonsterMapperTest.java
        • 3.动态SQL-if标签
          • 1.需求分析
          • 2.MonsterMapper.java添加@Param注解
          • 3.MonsterMapper.xml
          • 4.测试
        • 4.动态SQL-where标签
          • 1.需求分析
          • 2.MonsterMapper.java添加方法
          • 3.MonsterMapper.xml添加实现类
          • 4.测试
        • 5.动态SQL-choose标签
          • 1.需求分析
          • 2.MonsterMapper.java添加方法
          • 3.MonsterMapper.xml添加实现类
          • 4.测试
        • 6.动态SQL-foreach标签
          • 1.需求分析
          • 2.MonsterMapper.java添加方法
          • 3.MonsterMapper.xml添加实现类
          • 4.测试
        • 7.动态SQL-set标签(重点)
          • 1.需求分析
          • 2. MonsterMapper.java添加方法
          • 3.MonsterMapper.xml
          • 4.测试

1.动态SQL

1.基本介绍
1.为什么需要动态SQL

image-20240304161024014

2.基本说明

image-20240304161328438

3.动态SQL常用标签

image-20240304161355168

2.环境搭建
1.新建子模块

image-20240304161536794

2.删除不必要的两个文件夹

image-20240304161639688

3.创建基本结构

image-20240304162428796

4.父模块的pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>mybatis</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>Archetype - mybatis</name>
  <url>http://maven.apache.org</url>
  <modules>
    <module>mybatis_quickstart</module>
    <module>xml-mapper</module>
    <module>dynamic-sql</module>
  </modules>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.49</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.7</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <!--如果设置scope为test,则只能在test包下使用-->
      <scope>test</scope>
    </dependency>
  </dependencies>
  <!--在父模块中的pom.xml文件中配置在build的时候要扫描的文件,解决某些类型文件拷贝到target目录失败的问题-->
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <!--在java文件夹下的多级目录下的xml文件-->
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <!--在resources文件夹下的多级目录下的xml文件和properties文件-->
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
      </resource>
    </resources>
  </build>
</project>

5.jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root

6.mybatis-config.xml
  • 配置com.sun.entity的类型别名
  • 引入com.sun.mapper里的Mapper.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>
    <!--引入外部文件jdbc.properties-->
    <properties resource="jdbc.properties"/>

    <!--配置mybatis自带的日志,settings需要放到最前面-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--配置类型别名-->
    <typeAliases>
        <!--方式二:这样配置完了在这个包下的所有类都可以直接使用类名表示-->
        <package name="com.sun.entity"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <!--配置事务管理器-->
            <transactionManager type="JDBC"/>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置驱动-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--配置连接url-->
                <!--
                1.jdbc:mysql:协议
                2.127.0.0.1:3306:指定连接mysql的ip+端口
                3.mybatis:连接的db
                4.useSSL:使用安全连接
                5.&amp;:表示&
                6.useUnicode=true:使用unicode,防止编码错误
                7.characterEncoding=UTF-8:字符集使用utf-8
                -->
                <property name="url" value="${jdbc.url}"/>
                <!--用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--密码-->
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--包的方式引入含有Mapper.xml文件的类-->
        <package name="com.sun.mapper"/>
    </mappers>

</configuration>

7.MyBatisUtils.java
package com.util;

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 java.io.IOException;
import java.io.InputStream;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    //使用静态代码块初始化SqlSessionFactory
    static {
        try {
            //获取Mybatis配置文件的输入流
            String resource = "mybatis-config.xml";
            //默认是从类路径下获取资源,在maven中指的就是resources文件夹下,会映射到实际的工作目录
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
            //读取资源获取SessionFactory,可以理解为连接池
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //编写方法返回SqlSession
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

8.MonsterMapper.java
package com.sun.mapper;



/**
 * 这个接口用于声明操作monster表的方法
 *
 * @author 孙显圣
 * @version 1.0
 */
public interface MonsterMapper {

}

9.MonsterMapper.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">
<!--指定该xml文件和哪个接口对应-->
<mapper namespace="com.sun.mapper.MonsterMapper">

</mapper>
10.测试MonsterMapperTest.java
package com.sun.mapper;

import com.sun.entity.Monster;
import com.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class MonsterMapperTest {
    //两个属性
    private SqlSession sqlSession; //相当于连接
    private MonsterMapper monsterMapper;

    //编写方法完成初始化
    @Before //标注了Before之后表示了在执行目标测试方法前会执行该方法
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        //获取到MonsterMapper对象
        monsterMapper = sqlSession.getMapper(MonsterMapper.class);
        System.out.println(monsterMapper.getClass());
    }
    @Test

    public void test() {
        System.out.println("ttt");
    }

}

image-20240304163252656

3.动态SQL-if标签
1.需求分析

image-20240304163531716

2.MonsterMapper.java添加@Param注解
package com.sun.mapper;


import com.sun.entity.Monster;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 这个接口用于声明操作monster表的方法
 *
 * @author 孙显圣
 * @version 1.0
 */
public interface MonsterMapper {
    //使用@Param("age")注解来使得动态sql的test域可以取出这个age
    public List<Monster> findMonsterByAge(@Param("age") Integer age);
}

3.MonsterMapper.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">
<!--指定该xml文件和哪个接口对应-->
<mapper namespace="com.sun.mapper.MonsterMapper">
    <!--public List<Monster> findMonsterByAge(Integer age);
        要求:当用户输入的值不大于0则输出所有妖怪
    -->
    <select id="findMonsterByAge" resultType="Monster" parameterType="Integer">
        select * from monster where 1 = 1
        <!--这里的age是在参数中使用@Param注解取出的-->
        <if test="age >= 0">
            and age > #{age}
        </if>
    </select>
</mapper>
4.测试
    @Test
    public void findMonsterByAge() {
        List<Monster> list = monsterMapper.findMonsterByAge(10);
        for (Monster monster : list) {
            System.out.println(monster);
        }
        //关闭sqlsession
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
4.动态SQL-where标签
1.需求分析

image-20240304171800511

2.MonsterMapper.java添加方法
    public List<Monster> findMonsterByIdAndName(Monster monster);
3.MonsterMapper.xml添加实现类
    <!--public List<Monster> findMonsterByIdAndName(Monster monster);
        1.id小于0则不拼接,名字为空也不拼接
        2.where标签会自动清除没用的and
		3.如果传入的是对象,就不用使用@Param
    -->
    <select id="findMonsterByIdAndName" resultType="Monster" parameterType="Monster">
        SELECT * FROM monster
        <where>
            <if test="id >= 0">
                and id > #{id}
            </if>
            <if test="name != null and name != ''">
                and `name` = #{name}
            </if>
        </where>
    </select>
4.测试
    @Test
    public void findMonsterByIdAndName() {
        Monster monster = new Monster();
        monster.setId(4);
        monster.setName("牛魔王");
        List<Monster> monsters = monsterMapper.findMonsterByIdAndName(monster);
        for (Monster monster1 : monsters) {
            System.out.println(monster1);
        }
        //关闭sqlsession
        if (sqlSession != null) {
            sqlSession.close();
        }
    }

image-20240304185503494

5.动态SQL-choose标签
1.需求分析

当name不为空和id>0的时候有不同的操作

2.MonsterMapper.java添加方法
    public List<Monster> findMonsterByIdOrName_choose(Map<String, Object> map);
3.MonsterMapper.xml添加实现类
<!--    public List<Monster> findMonsterByIdOrName_choose(Map<String, Object> map);-->
    <select id="findMonsterByIdOrName_choose" parameterType="map" resultType="Monster">
        select * from `monster`
        <choose>
            <when test="name != null and name != ''">
                where `name` = #{name}
            </when>
            <when test="id > 0">
                where `id` = #{id}
            </when>
            <otherwise>
                where `salary` > 100
            </otherwise>
        </choose>
    </select>
4.测试
    @Test
    public void findMonsterByIdOrName_choose() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 2);
        map.put("name", "");
        List<Monster> list = monsterMapper.findMonsterByIdOrName_choose(map);
        for (Monster monster : list) {
            System.out.println(monster);
        }
    }
6.动态SQL-foreach标签
1.需求分析

查询id为1,2,3的妖怪

2.MonsterMapper.java添加方法
public List<Monster> findMonsterById_forEach(Map<String, Object> map);
3.MonsterMapper.xml添加实现类
    <select id="findMonsterById_forEach" parameterType="map" resultType="Monster">
        select * from `monster`
        <if test="ids != null and ids != ''">
            <where>
                id in
                <!--
                    map中传入一个ids集合为[1,2,3]
                    目标:id in (1,2,3)
                    collection:要遍历的集合
                    item:遍历的数据项
                    open:开始标志
                    close:结束标志
                    separator:数据间隔
                -->
                <foreach collection="ids" item="id" open="(" separator="," close=")">
                    <!--  这里取出的是item里的id-->
                    #{id}
                </foreach>
            </where>
        </if>
    </select>
4.测试
    @Test
    public void findMonsterById_forEach() {
        Map<String, Object> map = new HashMap<String, Object>();
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        //添加一个集合key为ids
        List<Monster> list = monsterMapper.findMonsterById_forEach(map);
        for (Monster monster : list) {
            System.out.println(monster);
        }
    }
7.动态SQL-set标签(重点)
1.需求分析

image-20240305144952009

2. MonsterMapper.java添加方法
    public void updateMonster_set(Map<String, Object> map);
3.MonsterMapper.xml
    <!--根据id来对表进行修改,如果没有传值则不修改那个字段-->
    <!--public void updateMonster_set(Map<String, Object> map);-->
    <!--UPDATE monster , birthday = '2020-1-2', email = 'libai@qq.com', gender = 1, name = '李白', salary = 12.2 WHERE id = 3-->
    <update id="updateMonster_set" parameterType="map">
        UPDATE monster
        <set>
            <if test="age != null and age != ''">
                 age = #{age},
            </if>
            <if test="birthday != null and birthday != ''">
                 birthday = #{birthday},
            </if>
            <if test="gender != null and gender != ''">
                 gender = #{gender},
            </if>
            <if test="name != null and name != ''">
                 name = #{name},
            </if>
            <if test="salary != null and salary != ''">
                 salary = #{salary},
            </if>
            <if test="salary != null and salary != ''">
                 salary = #{salary},
            </if>
        </set>
        where id = #{id}
    </update>
4.测试
    @Test
    public void updateMonster_set() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 3);
        map.put("age", 22);
        map.put("gender", 1);
        monsterMapper.updateMonster_set(map);
    }

image-20240305160803238

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1637106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

经典机器学习法---感知模型机

优质博文&#xff1a;IT-BLOG-CN 1、模型形式 感知机模型主要用于解决二分类问题&#xff0c;即响应变量Y是个二分类变量&#xff08;如性别&#xff09;。其基本思想是拟找出一个超平面S&#xff0c;将样本空间中的训练集分为两个部分&#xff0c;使得位于超平面S合一侧的点具…

匠心精神与创新力量:构筑网络安全的新防线

一、匠心精神在网络安全中的重要性 匠心精神代表着对工作的专注和对质量的极致追求。在网络安全领域&#xff0c;这意味着对每一个安全漏洞的深入挖掘&#xff0c;对每一项安全技术的精心打磨。亿林网络李璐昆的提名&#xff0c;正是对其在网络安全领域匠心精神的认可。 二、…

手把手教数据结构与算法:优先级队列(银行排队问题)

队列 基本概念 队列的定义 队列&#xff08;Queue&#xff09;&#xff1a;队列是一种常见的数据结构&#xff0c;遵循先进先出&#xff08;First-In-First-Out, FIFO&#xff09;的原则。在队列中&#xff0c;元素按照进入队列的顺序排列。队列是一个线性的数据结构&#x…

【PPT设计】颜色对比、渐变填充、简化框线、放大镜效果、渐变形状配图、线条的使用

目录 图表颜色对比、渐变填充、简化框线放大镜效果渐变形状配图 线条的使用区分标题与说明信息区分标题与正文,区分不同含义的内容**聚焦****引导****注解****装饰** 图表 颜色对比、渐变填充、简化框线 小米汽车正式亮相&#xff01;你们都在讨论价格&#xff0c;我全程只关…

【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、简单介绍Sizeof和Strlen1.1 Sizeof1.2 Strlen函数1.3 Sie…

几个容器网络问题实战解析

容器云平台和容器网络紧密结合&#xff0c;共同构建了容器化应用程序的网络基础设施&#xff0c;实现了容器之间的通信、隔离和安全性。文中容器云平台采用的容器网络组件是calico&#xff0c;这个是业界普遍采用的一种方案&#xff0c;性能及安全性在同类产品中都是比较好的。…

【UnityRPG游戏制作】Unity_RPG项目_玩家逻辑相关

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

Android Studio 调试:快速入门指南

作为一名Android应用开发人员&#xff0c;调试是你不可或缺的技能之一。通过调试&#xff0c;你可以定位和解决各种问题&#xff0c;包括崩溃、性能问题、UI错误等。在本文中&#xff0c;我们将分享一些实用的Android调试技巧&#xff0c;帮助你提高应用开发效率。 Android St…

Delta lake with Java--将数据保存到Minio

今天看了之前发的文章&#xff0c;居然有1条评论&#xff0c;看到我写的东西还是有点用。 今天要解决的问题是如何将 Delta产生的数据保存到Minio里面。 1、安装Minio&#xff0c;去官网下载最新版本的Minio&#xff0c;进入下载目录&#xff0c;运行如下命令&#xff0c;曾经…

动态规划——记忆化递归

1.情景导入 你应该知道斐波那契数列吧&#xff01;就是前两项之和等于这一项。如果你学过递归&#xff0c;你肯定会写这道题&#xff1a;输入一个N代表你要求的项数&#xff0c;然后输出斐波那契的第N项。这道题看似简单&#xff0c;实则也挺简单实则特别困难&#xff08;对于…

C++学习第十五课:类型转换运算符的深度解析

C学习第十五课&#xff1a;类型转换运算符的深度解析 类型转换是编程中常见的需求&#xff0c;C提供了多种类型转换方式&#xff0c;包括静态类型转换和动态类型转换。此外&#xff0c;还可以通过类型转换运算符自定义转换行为。本课将深入探讨C中的类型转换机制&#xff0c;包…

Visual Source Safe 安装与使用教程

1.VSS 的工作原理: Microsott的 vss讲所有的项目源文件(包括各种文件类型)以特有的方式存入数据库。用户成员不能对该数据库中的文件进行直接的修改,而是由版本管理器将该项目的远程序或是子项目的程序拷贝到各个用户成员自己的工作目录下进行调试和修改,然后将修改后的项目…

[ log日志画图]分割模型训练结束生成相关日志运用代码画图

文章目录 [ log日志画图]分割模型训练结束生成相关日志运用代码画图我的log文件&#xff1a;画图&#xff1a;1.loss1.1 loss是干嘛的1.2 代码1.3 生成图 2.DICE.IOU2.1 DICE,IOU是干嘛的(常规介绍)2.2 代码2.3 生成图小白tip [ log日志画图]分割模型训练结束生成相关日志运用代…

《Redis使用手册之Lua脚本》

《Redis使用手册之Lua脚本》 EVAL&#xff1a;执行脚本 127.0.0.1:6379> eval “return ‘hello world’” 0 “hello world” 127.0.0.1:6379> eval “return redis.call(‘set’,KEYS[1],ARGV[1])” 1 “message” “hello world” OK 127.0.0.1:6379> get message…

基于FPGA的数字信号处理(5)--Signed的本质和作用

前言 Verilog中的signed是一个很多人用不好&#xff0c;或者说不太愿意用的一个语法。因为不熟悉它的机制&#xff0c;所以经常会导致运算结果莫名奇妙地出错。其实了解了signed以后&#xff0c;很多时候用起来还是挺方便的。 signed的使用方法主要有两种&#xff0c;其中一种…

【Windows,亲测有效】手动激活Sublime Text

前言 Sublime Text 是一款非常好用的文本编辑器&#xff0c;但是免费版时不时会跳弹窗 本方法无毒无害&#xff0c;简单易上手 2023/12/22 更新&#xff1a;实测从 4143 支持到 4169 开始 先确保你用的是官方版本的 Sublime Text&#xff0c;还没下的可以去官方下载&#…

TiDB系列之:部署TiDB集群常见报错解决方法

TiDB系列之&#xff1a;部署TiDB集群常见报错解决方法 一、部署TiDB集群二、unsupported filesystem ext3三、soft limit of nofile四、THP is enabled五、numactl not usable六、net.ipv4.tcp_syncookies 1七、service irqbalance not found,八、登陆TiDB数据库 一、部署TiDB…

【ARM 裸机】NXP 官方 SDK 使用

在前几节中&#xff0c;学习了如何编写汇编的 led 驱动、C 语言的 led 驱动、模仿 STM32 进行开发&#xff0c;我们都是自己写外设寄存器的结构体&#xff0c;外设非常的多&#xff0c;写起来费时费力&#xff0c;NXP 针对 I.MX6ULL 编写了一个 SDK 包&#xff0c;这个 SDK 包就…

C++ | Leetcode C++题解之第59题螺旋矩阵II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> generateMatrix(int n) {int num 1;vector<vector<int>> matrix(n, vector<int>(n));int left 0, right n - 1, top 0, bottom n - 1;while (left < r…

【C++】一篇文章带你深入了解stack、queue 和 priority_queue

目录 一、stack的介绍和使用1.1 stack的介绍1.2 stack的使用1.2.1.1 [stack对象的构造](https://legacy.cplusplus.com/reference/stack/stack/stack/)1.2.1.2 stack对象的容量操作1.2.1.2.1 [empty()函数](https://legacy.cplusplus.com/reference/stack/stack/empty/)1.2.1.2…