MyBatis 环境搭建+基本使用

目录

  • 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 标签最常见的使用:批量删除

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JVM学习(十三):面试中绕不开的String

目录 一、String 的基本特性 1.1 String类的声明 1.2 String的存储方式在jdk9中的变更 1.3 Stirng 的不可变性 二、String的内存分配 2.1 字符串常量池是什么 2.2 底层原理与默认值 2.3 字符串常量池所在位置 三、字符串的拼接操作 3.1 拼接操作结果存放位置 …

es elasticsearch 九 索引index 定制分词器 type结构后期弃用原因 定制动态映射 动态映射模板 零停机重建索引

目录 索引index 定制分词器 Type底层结构及弃用原因 定制 dynamic mapping 定制dynamic mapping template 动态映射模板 零停机重建索引 生产环境应该度别名数据 索引index Put /index Stings 分片 Mapping 映射 Aliases 别名 增加 Put my_index2 { "se…

软考A计划-试题模拟含答案解析-卷七

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

从C语言到C++_12(string相关OJ题)(leetcode力扣)

上一篇已经讲了string类的接口函数&#xff0c;然后根据查文档刷了牛客和力扣58最后一个单词的长度&#xff0c; 还有力扣415字符串相加&#xff0c;这篇继续跟着查文档来刷力扣题&#xff0c;体会C刷题的方便。 目录 917. 仅仅反转字母 - 力扣&#xff08;LeetCode&#xf…

Linux 实操篇-组管理和权限管理

Linux 实操篇-组管理和权限管理 Linux 组基本介绍 在linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在linux 中每个文件有所有者、所在组、其它组的概念。 所有者所在组其它组改变用户所在的组 文件/目录所有者 一般为文件的创建者,谁创建了该文件&#x…

计算机视觉:卷积核的运行过程

本文重点 我们前面从直观角度理解了卷积神经网络的卷积在特征提取的作用,本节课程我们从数学角度来看一下,卷积是如何计算的? 计算步骤 1. 将卷积核与输入图像的某一部分进行逐元素相乘。 2. 将相乘后的结果求和,得到卷积核在该部分的输出值。 3. 重复以上步骤,将卷积核…

【shiro】shiro整合JWT——3.执行流程

前言 shiro整合JWT系列&#xff0c;主要记录核心思路–如何在shiroredis整合JWTToken。 上一篇中&#xff0c;主要讲如何在shiro框架中配置Jwt&#xff0c;以及token执行的流程。 该篇主要梳理整个代码的执行流程。 ps&#xff1a;本文主要以记录核心思路为主&#xff0c;以下…

uCOSii消息邮箱管理

uCOSii消息邮箱管理 (MESSAGE MAILBOX MANAGEMENT) 消息邮箱主要用于中断和任务之间进行邮件传递&#xff0c;或者是在任务与任务之间进行邮件交换。 我个人觉得&#xff0c;了解uCOSii消息邮箱的几个重要函数&#xff0c;还是有必要的。不是所有人都给我们测试案例。 1、重…

R语言混合效应(多水平/层次/嵌套)模型及贝叶斯实现技术

回归分析是科学研究中十分重要的数据分析工具。随着现代统计技术发展&#xff0c;回归分析方法得到了极大改进。混合效应模型&#xff08;Mixed effect model&#xff09;&#xff0c;即多水平模型&#xff08;Multilevel model&#xff09;/分层模型(Hierarchical Model)/嵌套…

如何快速运用R语言实现生物群落(生态)数据统计分析与绘图

R 语言作的开源、自由、免费等特点使其广泛应用于生物群落数据统计分析。生物群落数据多样而复杂&#xff0c;涉及众多统计分析方法。本次以生物群落数据分析中的最常用的统计方法回归和混合效应模型、多元统计分析技术及结构方程等数量分析方法为主线&#xff0c;通过多个来自…

Linux:查看进程。

Linux&#xff1a;查看进程。 windows linux TTY如果是&#xff1f;说明是不是终端(控制台)启动的&#xff0c;而是系统内部自己启动的。 TIME是启动Linux后&#xff0c;这个进程一共占用了cpu多少时间00…

QT 设计ROS GUI界面订阅和发布话题

QT 设计ROS GUI界面订阅和发布话题 主要参考下面的博客 ROS项目开发实战&#xff08;三&#xff09;——使用QT进行ROS的GUI界面设计&#xff08;详细教程附代码&#xff01;&#xff01;&#xff01;&#xff09; Qt ROS 相关配置请看上一篇博客 首先建立工作空间和功能包&a…

【探索】机器指令翻译成 JavaScript

前言 前些时候研究脚本混淆时&#xff0c;打算先学一些「程序流程」相关的概念。为了不因太枯燥而放弃&#xff0c;决定想一个有趣的案例&#xff0c;可以边探索边学。 于是想了一个话题&#xff1a;尝试将机器指令 1:1 翻译 成 JavaScript&#xff0c;这样就能在浏览器中&am…

Java程序设计入门教程-- if 条件语句

目录 单分支选择语句&#xff08;if&#xff09; 双分支选择语句&#xff08;if…else&#xff09; 嵌套if语句 单分支选择语句&#xff08;if&#xff09; 情形 当判断条件满足时&#xff0c;执行语句体S&#xff0c;而不满足则什么都不做。 格式 if &#xff08;条件判断表…

【计算机视觉 | 目标检测】术语理解6:ViT 变种( ViT-H、ViT-L ViT-B)、bbox(边界框)、边界框的绘制(含源代码)

文章目录 一、ViT & ViT变种1.1 ViT的介绍1.2 ViT 的变种 二、bbox&#xff08;边界框&#xff09;三、边界框的绘制 一、ViT & ViT变种 1.1 ViT的介绍 ViT&#xff0c;全称为Vision Transformer&#xff0c;是一种基于Transformer架构的视觉处理模型。传统的计算机视…

java企业工程项目管理系统平台源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

回调函数与钩子函数的区别,另QT中connect函数的实现,lambda的使用

1、钩子函数是回调函数的一种 广泛来说两者都是一样的 严格来说 钩子函数的函数名早已被定义好&#xff0c;只是函数内部需要用户在应用层来定义&#xff0c; 1&#xff09;可以完全通过宏来实现系统是否调用该函数&#xff08;底层不封闭&#xff0c;修改宏的参数实现是否编…

【2023 · CANN训练营第一季】MindSpore模型快速调优攻略 第二章——MindSpore调试调优

1.生态迁移 生态迁移工具使用示例 生态迁移工具技术方案 不同框架间模型定义前端表达差别巨大(相同算子的API技术难点 、 算子功能、模型构建方式差别较大)&#xff1b; 对于同一框架&#xff0c;不管前端表达差异如何&#xff0c;最终对应的计算 图是相似的。因此提出&#x…

Kubernetes部署+kubesphere管理平台安装

Kubernetes官网&#xff1b;kubesphere官网 不论是Kubernetes官网还是找的其它部署步骤&#xff0c;基本都是推荐搭建集群的方式&#xff0c;是为了实现高可用.....等等&#xff0c;这样一来至少需要两台或三台的服务器来搭建&#xff0c;这样对我们的成本也是非常大的&#xf…

Axure教程——直方图(中继器)

本文将教大家如何用AXURE用中继器制作直方图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://yjkepz.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87842701 二、制作方法 &#xff08;1&#xff09;制作刻度表 设计5个刻…