MyBatis 环境搭建+基本使用

news2024/12/24 8:23:38

目录

  • MyBatis
    • 创建MyBatis环境搭建
    • MyBatis模式开发
    • MyBatis 获取动态参数(查询操作)
      • ${} 直接替换
      • #{} 占位符模式替换
      • like查询(模糊查询)
      • 多表查询
        • 一对一的表映射
        • 一对多的表映射
    • 增、删、改操作
      • 改操作
      • 删除操作
      • 增加操作
        • 添加用户
        • 添加用户并获取用户id
    • 返回类型与返回字典映射
      • 返回类型 resultType
      • 返回字典映射 resultMap
    • 动态SQL
      • \<if\>标签
      • \<trim\>标签
      • \<where\>标签
      • \<set\>标签
      • \<foreach\>标签

MyBatis是优秀的持久层框架,支持自定义SQL,存储过程以及高级映射。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
使用MyBatis是更简单完成程序和数据库交互的工具,可以更简单的操作和读取数据库工具。

MyBatis官网

MyBatis

MyBatis是基于JDBC的,在JDBC上又封装了一层

创建MyBatis环境搭建

和maven项目不同的两步:

  1. 添加MyBatis框架支持 (老项目 / 新项目)
  2. 设置MyBatis的配置信息
    • 设置数据库链接的相关信息
    • 配置 MyBatis xml 的保存路径和 xml 命名模式
# 数据库的连接字符串设置
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=111
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 设置MyBatis
mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml

在这里插入图片描述
在这里插入图片描述

添加MyBatis框架支持
在这里插入图片描述
注意:第一次创建好了MyBatis项目之后,启动会报错。
在这里插入图片描述
需要在application.properties下设置数据库的连接字符串设置和 MyBatis 的 XML ⽂件配置。
在这里插入图片描述

# 数据库的连接字符串设置
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=111
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 设置MyBatis
mybatis.mapper-locations=classpath:/mybatis/*Mapper.xml

MyBatis模式开发

MyBatis模式开发由两部分组成

  1. interface :让其他层可以注入使用的接口
  2. MyBatis xml:具体实现sql【他是上面interface的实现】
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

MyBatis 获取动态参数(查询操作)

${} 直接替换

MyBatis 获取动态参数有两种实现:

  1. ${paramName} 直接替换
    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id=${uid}
<!--    如果param和形参中的值不一样,需要使用@Param中的参数    -->
    </select>

在这里插入图片描述

#{} 占位符模式替换

  1. #{paramName} 占位符模式
    是一种预执行,可以有效的排除SQL的安全问题
    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id=#{uid}
    </select>

在这里插入图片描述

    @Test
    void login() {
        String username = "admin";
        String password = "' or 1='1";
        UserEntity inputUser = new UserEntity();
        inputUser.setUsername(username);
        inputUser.setPassword(password);
        UserEntity user = userMapper.login(inputUser);
        System.out.println(user);
    }
    <select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username='${username}' and password='${password}'
    </select>

没有输入密码,但是可以构造,得到用户数据
在这里插入图片描述
$:直接替换
只要or前后有一个条件满足即可

select * from userinfo where username='${username}' and password='' or 1='1'

#是预执行处理,填充的东西只看做一个字符串,不会查到用户数据

    <select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username=#{username} and password=#{password}
    </select>

在这里插入图片描述

$:直接替换,当需要传递一个SQL关键字的时候比较适合使用
比如需要对数据进行倒序或者正序排序时

//UserMapper.java
    List<UserEntity> getAllByIdOrder(@Param("ord") String ord);
//UserMapper.xml
    <select id="getAllByIdOrder" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo order by id ${ord}
    </select>
//UserMapperTest
    @Test
    void getAllByIdOrder() {
        List<UserEntity> list = userMapper.getAllByIdOrder("desc");
        System.out.println(list.size());
    }

like查询(模糊查询)

    //根据用户名模糊查询
    List<UserEntity> getListByName(@Param("username") String username);
    <select id="getListByName" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username like concat('%', #{username},'%')
    </select>
    @Test
    void getListByName() {
        String username = "oo";
        List<UserEntity> list = userMapper.getListByName(username);
        list.stream().forEach(System.out::println);
    }

多表查询

一对一的表映射

(企业中几乎不用)

一对多的表映射

增、删、改操作

改操作

修改密码

//UserMapper.java
    //修改密码
    int updatePassword(@Param("id")Integer id,
                       @Param("password") String password,
                       @Param("newPassword") String newPassword);
<!--  UserMapper.xml  -->
<!--  select 要求必须设置两个属性,update设置一个参数就行,update默认会返回一个受影响的行数,返回类型默认是int  -->
    <update id="updatePassword">
        update userinfo set password=#{newPassword}
        where id=#{id} and password=#{password}
    </update>

在UserMapper.java下右键生成updatePassword的Test

//UserMapperTest.java
    @Transactional  //事务(执行前新建事务,执行完进行回滚) 该注解让操作不污染数据库,可以加在类上,也可以加在方法上。
    @Test
    void updatePassword() {
        int result = userMapper.updatePassword(1, "123456", "aaaaa");
        System.out.println("修改:" + result);
    }

删除操作

//UserMapper.java
    //删除用户
    int delById(@Param("id") Integer id);
<!--  UserMapper.xml  -->
<!--  删除  -->
    <delete id="delById">
        delete from userinfo where id=#{id}
    </delete>
//UserMapperTest.java
    @Transactional
    @Test
    void delById() {
        int id = 1;
        int result = userMapper.delById(id);
        System.out.println("删除结果:" + result);
    }

增加操作

添加用户

//UserMapper.java
    //添加操作
    int addUser(UserEntity user);
<!--  UserMapper.xml  -->
<!--  添加  返回影响行数-->
    <insert id="addUser">
        insert into userinfo(username, password) values(#{username}, #{password})
    </insert>
//UserMapperTest.java
    @Test
    void addUser() {
        UserEntity user = new UserEntity();
        user.setUsername("root");
        user.setPassword("123456");
        int result = userMapper.addUser(user);
        System.out.println("添加用户" + result);
    }

添加用户并获取用户id

//UserMapper.java
    int addUserGetId(UserEntity user);
<!--  UserMapper.xml  -->
<!--  数据库中要给id设置自增主键,不然这些会报错  -->
<!--  useGeneratedKeys="true"  表示是否自动生成id(主键) 默认为false  -->
<!--  开启自动生成主键后,keyProperty表示将生成的主键赋值给哪个属性字段上,放在id字段  -->
<!--    添加 返回影响行数 和 id-->
    <insert id="addUserGetId" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo(username, password) values(#{username}, #{password})
    </insert>
//UserMapperTest.java
    @Test
    void addUserGetId() {
        UserEntity user = new UserEntity();
        user.setUsername("root");
        user.setPassword("123456");
        int result = userMapper.addUserGetId(user);
        System.out.println("添加结果:" + result);
        System.out.println("ID:" + user.getId());
    }

返回类型与返回字典映射

返回类型 resultType

大多数的场景都可以使用resultType进行返回。使用方便,直接定义实体类即可

返回字典映射 resultMap

resultMap的使用场景

  • 字段名称和程序中的属性名不同,使用resultMap配置映射
  • 一对一和一对多关系可以使用resultMap映射并查询数据

动态SQL

动态SQL是MyBatis的强大特性之一,能够描述不同条件下不同SQL的拼接。允许在XML中写逻辑判断
保证了数据的一致性

<if>标签

有时候有必填字段和⾮必填字段,如果在添加的时候有不确定的字段传⼊,需要使用动态标签 <if> 判断

    int addUser2(UserEntity user);
    <insert id="addUser2">
        insert into userinfo(username, password
        <if test="photo != null and photo !=''">      <!--   这里test里面判断的key是属性,不是数据库字段  -->
            ,photo       <!--  数据库字段  -->
        </if>
        ) values(#{username}, #{pwd}
        <if test="photo != null and photo !=''">
            ,#{photo}     <!--  这里是属性,不是数据库字段 (特殊字符 #{} 等,里面的都属于程序里面的)  -->
        </if>
        )
    </insert>
    @Transactional
    @Test
    void addUser2() {
        String username = "ss";
        String password = "1008611";
        String photo = "this is a photo";
        UserEntity user = new UserEntity();
        user.setUsername(username);
        user.setPwd(password);
        user.setPhoto(photo);
        int result = userMapper.addUser2(user);
        System.out.println("添加:" + result);
    }

<trim>标签

如果所有的字段都是非必填的情况下,只使用if标签就无法解决问题了。
就要使用<trim>标签结合<if>标签,对多个字段都采取动态生成的方式。

<trim>标签属性:

  • prefix:整个语句块,以prefix的值为前缀
  • suffix:整个语句块,以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除的前缀,有则去除,没有也不会报错
  • suffixOverrides:表示整个语句块要去除的后缀

<trim>标签的处理方法:

  • 基于prefix配置,在开始部分加上 (
  • 基于suffix配置,在结束部分加 )
  • 在多个 <if> 组织的语句后都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于suffixOverrides配置去掉最后一个 ,
  • <if test="createTime!=null">中的 createTime 是传入对象的属性

使用 trim 什么都不传的话会报错

select * from articleinfo
where
<trim suffixOverrides="and">
    <if test="id != null and id > 0">
        id=#{id} and
    </if>
    <if test="title != null and title != ''">
        title like concat('%', #{title},'%')
    </if>
</trim>

当MyBatis中多个都是非必传参数的解决方案
① 1=1


<!--除非在最前面加上 1=1 -->
<!--   这样是可行的    -->
select * from articleinfo
where 1=1
<trim prefixOverrides="and">
    <if test="id != null and id > 0">
         and id=#{id}
    </if>
    <if test="title != null and title != ''">
         and title like concat('%', #{title},'%')
    </if>
</trim>

② 在trim中使用where作为前缀和and作为整个语句块要去除的后缀
当trim中生成了代码,才会添加<trim>中的前缀和后缀,如果trim中没有生成代码,前缀和后缀都会省略

<select id="getListByIdOrTitle" resultType="com.example.demo.entity.VO.ArticleInfoVO">
    select * from articleinfo
    <trim prefix="where" suffixOverrides="and">
        <if test="id != null and id > 0">
            id=#{id} and
        </if>
        <if test="title != null and title != ''">
            title like concat('%', #{title},'%')
        </if>
    </trim>
</select>

③ where标签

<where>标签

where标签是专门用来解决多个都是非必传参数的。

<where>会自动帮你取出最前面的 and 关键字,但要注意,使用where标签不会自动帮你去除最后的and标签。
where 会自动检测 <where>内是否有数据传入,如果没有就不会生成where语句

select * from articleinfo
<where>
    <if test="id != null and id > 0">
        id=#{id}
    </if>
    <if test="title != null and title != ''">
        and title like concat('%', #{title},'%')
    </if>
</where>

<set>标签

<set>会自动取出最后面的关键字。

<update id="updateById" parameterType="org.example.model.User">
	 update user
	 <set>
		 <if test="username != null">
		 	username=#{username},
		 </if>
		 <if test="password != null">
		 	password=#{password},
		 </if>
		 <if test="sex != null">
		 	sex=#{sex},
		 </if>
	 </set>
	 where id=#{id}
</update>

<foreach>标签

对集合进行遍历
常用属性:

  • collection:传递过来的集合的名称,List,set,map或数组
  • item:集合中遍历的每一个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的分隔符

使用foreach 标签最常见的使用:批量删除

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

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

相关文章

chatgpt赋能python:Python中的英文单词

Python中的英文单词 Python是一种流行的编程语言&#xff0c;它具有人类易读性、功能强大、支持多种编程范例等特点。Python中包含着大量的英文单词&#xff0c;这些单词在Python编程中极为重要&#xff0c;因为它们直接影响代码的可读性和理解难度。本文将介绍一些最常用的Py…

Go开发学习 | 如何使用Gomail.v2模块包发送邮箱验证码消息及附件学习记录

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1a;[ https://www.weiyigeek.top ] 博客&…

vulhub-Jarbas(易)

打靶练习Jarbas 0x00 部署0x01 信息收集&#xff1a;端口扫描、服务发现0x02 路径爬取0x03 反弹shell0x04 内网信息收集0x05 crontab定时任务提权0x06 总结 0x00 部署 靶机&#xff1a;下载地址 宿主机&#xff1a;kali2021版本 0x01 信息收集&#xff1a;端口扫描、服务发现…

《计算机组成原理》唐朔飞 第9章 控制单元的功能 - 学习笔记

写在前面的话&#xff1a;此系列文章为笔者学习计算机组成原理时的个人笔记&#xff0c;分享出来与大家学习交流。使用教材为唐朔飞第3版&#xff0c;笔记目录大体与教材相同。 网课 计算机组成原理&#xff08;哈工大刘宏伟&#xff09;135讲&#xff08;全&#xff09;高清_…

git (本地仓库)和(远程仓库)之间的代码推送:013

这里先说明一下循序&#xff1a; 1. 创建(远程仓库)和(本地仓库) 2. 创建(远程仓库)和(本地仓库)之间的链接 3. 将(本地仓库)的代码推通过命令送到(远程仓库)&#xff1b;将(本地仓库)的代码通过(TortoiseGit小乌龟)推送到(远程仓库) 1. 创建(远程仓库)和(本地仓库)&#xff0c…

PHP异步:在PHP中使用 fsockopen curl 实现类似异步处理的功能

PHP从主流来看&#xff0c;是一门面向过程的语言&#xff0c;它的最大缺点就是无法实现多线程管理&#xff0c;其程序的执行都是从头到尾&#xff0c;按照逻辑一路执行下来&#xff0c;不可能出现分支&#xff0c;这一点是限制php在主流程序语言中往更高级的语言发展的原因之一…

C++实现sqlite单表增删改查的详细步骤

1.环境准备 coding之前需要先安装好C的集成开发环境&#xff0c; 我这里选择的是Visual Studio 2022&#xff0c;本来想使用CLion的&#xff0c; 但是破解太麻烦&#xff0c;懒得整了。 Visual Studio 2022 2.项目创建及编码 启动visual studio, 点击创建项目&#xff0c;选…

《MYSQL必知必会》读书笔记1

目录 行 主键 MYSQL工具 使用MYSQL 连接 检索数据 检索&#xff08;SELECT&#xff09; 限制结果&#xff08;LIMIT&#xff09; 排序检索&#xff08;ORDER BY&#xff09; 过滤数据&#xff08;WHERE&#xff09; 过滤数据&#xff08;AND、OR&#xff09; 通配符…

软件测试总结

软件生命周期(SDLC)的六个阶段 1、问题的定义及规划 此阶段是软件开发方与需求方共同讨论&#xff0c;主要确定软件的开发目标及其可行性。 2、需求分析 在确定软件开发可行的情况下&#xff0c;对软件需要实现的各个功能进行详细分析。需求分析阶段是一个很重要…

ML | 6 支持向量机

ML | 6 支持向量机 文章目录 ML | 6 支持向量机SVM介绍线性不可分数据线性可分数据 寻找最大间隔分类器求解的优化问题 SMO高效优化算法简化版SMO处理小规模数据集伪代码程序清单 完整Platt SMO 算法加速优化完整 Platt SMO的支持函数完整Platt SMO算法中的优化例程完整Platt S…

记录--Vue3自定义一个Hooks,实现一键换肤

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 核心 使用CSS变量, 准备两套CSS颜色, 一套是在 light模式下的颜色,一套是在dark模式下的颜色dark模式下的 CSS 权重要比 light 模式下的权重高, 不然当我们给html添加自定义属性[data-themedark]的时候…

CVPR 2023 | 南大王利民团队提出LinK:用线性核实现3D激光雷达感知任务中的large kernel...

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【Transformer】微信交流群 【CVPR 2023】LinK&#xff1a;用线性核实现3D激光雷达感知任务中的large kernel 本文介绍我们媒体计算研究组&#xff08;MCG&#xff09;在3D激…

chatgpt赋能python:Python中的提取函数——数据清洗中必不可少的利器

Python中的提取函数——数据清洗中必不可少的利器 数据清洗是数据分析过程中不可或缺的一步&#xff0c;而Python中的提取函数则是数据清洗中必不可少的利器。本文将重点介绍一些Python中常用的提取函数&#xff0c;以帮助数据分析师更好地应对实际问题。 什么是提取函数&…

react antd Modal里Form设置值不起作用

问题描述&#xff1a; react antd Modal里Form设置值不起作用&#xff0c;即使用form的api。比如&#xff1a;编辑时带出原有的值。 造成的原因&#xff1a;一般设置值都是在声明周期里设置&#xff0c;比如&#xff1a;componentDidMounted里设置&#xff0c;hook则在useEff…

云网络安全与数据中心安全

近年来&#xff0c;许多云架构师宣称随着公共云的采用&#xff0c;网络安全性将消亡。然而&#xff0c;网络安全仍然是最大的安全市场之一&#xff0c;并且是每个主要云服务提供商 (CSP) 在过去几年中推出重要新产品的领域。 网络对安全仍然至关重要&#xff0c;即使在云中也是…

【软考系统规划与管理师笔记】第4篇 信息技术服务知识

目录 1 产品、服务和信息技术服务 1.1 产品 1.2 服务 1.3 信息技术服务 2运维、运营和经营 2.1运维 2.2运营 2.3经营 3 IT治理 4 IT服务管理 4.1传统管理方式 4.2体系化管理方式 5项目管理 6质量管理理论 6.1质量管理发展历史 6.2质量管理常见理论方法 6.3质…

【公网远程Jellyfin】——本地部署Jellyfin影音服务器

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

面向Java开发者的ChatGPT提示词工程(5)

GPT 的局限性 在探讨开发大型语言模型应用程序时&#xff0c;我们必须认识到 GPT 存在一些局限性。这些限制对于我们保持清醒的头脑至关重要。 尽管在 GP T的训练过程中融入了大量知识&#xff0c;但它并非能够完美地记住所见之物&#xff0c;并且对这些知识的边界了解有限。…

玩转用户旅程地图

图&#xff1a;史江鸿 从事需求分析和产品设计工作已经有几个年头了&#xff0c;我很享受这个职业。因为在这段职业历程中&#xff0c;我学到了很多有意思的方法和工具&#xff0c;用户旅程地图就是其中一个。 如今在国内外许多IT公司&#xff0c;用户旅程地图已经成为需求分析…

ElasticSearch安装部署

ElasticSearch安装部署 简介 全文搜索属于最常见的需求&#xff0c;开源的 Elasticsearch &#xff08;以下简称 es&#xff09;是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。 Elasticsearch简称es&…