MyBatis操作数据库表和动态SQL的使用

news2024/11/24 22:49:04

目录

1.MyBatis开发环境的搭建和测试

2.MyBatis基本操作

2.0 准备工作

2.1 新增操作

2.2 删除、修改、查询操作

2.3 #{param} 和 ${param}的使用和区别

2.4 实体对象属性和数据库字段名称不同时如何映射?

3. MyBatis多表查询

3.0 准备工作

3.1 一对一的表的映射

3.2 一对多的表的映射

4.MyBatis动态SQL

4.0 准备工作

4.1 if-标签

4.2 trim-标签

4.3 where-标签

4.4 set-标签

4.5 foreach-标签


1.MyBatis开发环境的搭建和测试

MyBatis环境的搭建和测试可以参考之前发布的:MyBatis基本介绍以及开发环境的搭建和测试

2.MyBatis基本操作

我们先来使用MyBatis实现基本表的增删改查操作,在熟悉了这些基本操作后,再来学习MyBatis多表查询的实现。在进行学习之前,我们还是来回顾下MyBatis在我们后端程序中的地位:


我们在上一篇文章中学习到,MyBatis是通过定义mapper接口并找到对应的实现接口的xml文件整合,最后动态生成sql,借助jdbc操作来操作数据库的。所以我们对数据库表的操作从整体上应当分为两步:

  1. 定义mapper接口
  2. 定义实现mapper接口的MyBatis的XML文件

接下来我们通过学习MyBatis的基本操作来理解上述它操作数据库的两个步骤。下面我们的操作都基于下面这个项目的框架模板进行:

2.0 准备工作

 下面我们将要学习的的四种基本操作基于之前搭建环境时在数据库创建的一张user表来实现。在开始之前我们要先创建好用户相关的mapper接口和和数据库中user表对应的实体映射类,如下图:

2.1 新增操作

MyBatis实现基本新增操作的整体步骤:

  1. 在UserMapper接口中声明新增用户的方法
  2. 在对应的实现接口的xml文件中编写<insert>标签实现接口方法

实现过程中的注意事项和实现细节如下图:

2.2 删除、修改、查询操作

这些操作与2.1中的实现步骤类似,我们将其总结到了一块:

  1. 在UserMapper接口中定义相关的服务方法
  2. 在UserMapper.xml文件中选用对应的标签并编写sql语句实现接口中的方法

其中,各个操作的详细步骤和注意事项如下:

2.3 #{param} 和 ${param}的使用和区别

在上面的UserMapper的xml文件中,我们提到对于sql语句中未知量的赋值可以通过#{param}或者${param}赋值。那么既然都可以用来给sql语句赋值,那么它们之间有什么使用上的区别呢?(param:可能是传递的对象中的属性值也可能是传递的参数值)


1. '$'是直接替换,'#'是预处理。

这样说可能我们都不太好理解,我们来实际应用中看一下:

2.使用‘$’可能会存在sql注入的问题,使用'#'是安全的。

既然‘$’是直接替换,那么sql注入的安全问题就来了,下面我们来看一下使用$时带来的sql注入安全问题:


 那既然$和#都能实现需求,为什么不直接全是用#而还要有$呢?

这是因为在需要传递的参数是数据库中的关键字时,比如需要升序或降序排序的场景下我们必须使用$来拼接as或者desc字段,只能使用$,使用#就无法实现这个功能了。

比如:

-- 正常情况下,使用$传递排序参数(asc、desc)数按照id字段升序排列用户的sql语句
select * from user order by id asc;

-- 而使用 # 传递排序参数的sql语句形态为:(错误sql❌)
select *from user order by id 'asc';

2.4 实体对象属性和数据库字段名称不同时如何映射?

不知道大家有没有发现,我们在上面User实体类中有些属性的命名是不规范的,这是为了符合数据库的规范以求能够映射数据到相应实体对象的字段上。

同时在实际的开发中,由于开发人员和数据库设计人员可能不是同一个人来完成的,同时数据库规范和Java开发规范优势不相同的。那么就非常可能存在数据库表的字段名和开发中实体类的属性名不相同。那么在默认查询时使用我们的select标签的resultType指定的实体对象中的属性名由于和数据库中对应表的字段名不同,就不能正常映射数据库表中字段的值了。那么应该如何解决这种映射问题呢?我总结了以下两种方法:


1. 写查询语句时将查询字段重命名为我们实体对象中对应的属性名,即可正确映射。


 

2.使用resultMap属性,设计表字段和实体类属性的映射关系。

3. MyBatis多表查询

3.0 准备工作

为了学习MyBatis多表查询,我们在数据库中再创建一张评论表,这个评论表中有一个用户编号属性来指明该条评论是那个用户发表的,如下:


 对数据库中的评论表,在程序中创建Comment实体以及CommentMapper接口和实现的xml文件:

3.1 一对一的表的映射

这里我们通过查询评论表来学习一对一的表的映射。在我们返回给前端评论表中指定评论的信息时,需要返回的是评论的用户而不是评论表中的用户的id信息。评论表中的用户和用户表中的用户是一对一的关系,要实现返回给前端的数据中包含评论的相关信息以及评论的用户的名称而不是评论用户id,这个时候我们应该怎么做呢?


定义一个Comment视图实体对象,其中包含用户名属性。在进行数据库查询时使用联表查询,返回给前端这个视图实体对象中的信息即可!

如下图所示:

3.2 一对多的表的映射

如果现在我们要根据用户编号查询其发布的所有评论?又该如何实现呢?其实虽然用户和评论之间存在一对多的关系,但是仔细一看就会发现,我们的评论表中就存在着用户编号,所以我们通过单表查询就可以完成这个需求:

  

4.MyBatis动态SQL

4.0 准备工作

为了学习MyBatis动态SQL中使用的标签,我们接着上面的学习,再在MySQL的user用户表中新增一个默认约束的头像字段。下面我们的学习将使用到这个字段。

4.1 if-标签

在MyBatis中,if标签常用来判断:当某一条件满足时才进行SQL语句的拼装,这个判断条件写在MyBatis的xml文件中的if标签的test属性中。

<insert id="addDefault"  useGeneratedKeys="true" keyProperty="id">
    insert into user(
    username,
    password
    <if test="photo != null">
        ,photo
    </if>)
    values (
    #{username},
    #{password}
    <if test="photo != null">
        , #{photo}
    </if>)
</insert>

比如现在的需求,用户在注册时可以不上传头像,此时默认使用数据库中默认约束所指定的头像信息。那么我们应该如何编写SQL语句呢?if标签使用的注意事项和细节又有哪些呢?让我们通过实现上面的需求来一起探索:

4.2 trim-标签

在4.1的需求中,只有photo是一个选填项。如果现在有一个需求:所有用于填写的字段都是选填项,在数据库中也有对应的默认值约束。这个时候又应该怎么实现呢?

很显然,此时就不能再继续使用if标签了,这是因为:


于是这个时候就需要我们的trim标签登场了!我们先来看下trim标签有哪些关键字:

  1. prefix——前缀值
  2. suffix——后缀值
  3. prefixOverrides——整个语句块要去掉的前缀
  4. suffixOverrides——整个语句块要去掉的后缀
<insert id="addAllDefault" useGeneratedKeys="true" keyProperty="id">
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
            username,
        </if>
        <if test="password != null">
            password,
        </if>
        <if test="photo != null">
            photo,
        </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
        <if test="username != null">
            #{username},
        </if>
        <if test="password != null">
            #{password},
        </if>
        <if test="photo != null">
            #{photo},
        </if>
    </trim>
</insert>

我们使用trim标签来实现上述当所有字段非必填时的用户注册的需求,同时总结一下trim标签的使用注意事项及细节:

4.3 where-标签

听名知意😄,where想必就是给我们SQL语句中where判读条件使用的。使用where标签时,有以下几个细节:

  1. 使用where标签时,我们不用再手写sql语句中的where关键字。
  2. 当where标签中没有任何条件时,where关键字会被省略
  3. where标签会帮助我们删除SQL中的前缀 ‘and’关键字
  4. 通trim标签一致,where标签通常也和if标签搭配使用
<select id="getUserByNameOrPwd" resultType="com.example.demo.entity.User">
    select id,username,password,createtime 'createTime',photo
    from user
    <where>
        <if test="username != null">
            and username=#{username}
        </if>
        <if test="password != null">
            and password=#{password}
        </if>
    </where>
</select>

上面这种学习where标签的方式还不太直观,假设现在我们要实现管理员根据用户名或者密码查询指定user表中符合条件的用户的操作,下面我们使用MyBatis提供的where标签实现动态查询SQL实现上述需求:

4.4 set-标签

用来动态设置我们再MyBatis的xml文件中编写的sql语句中的set字段后的值,set标签的使用细节及注意事项如下:

  1. set标签中没有我们必须要去指定的关键字
  2. set标签会帮助我们删除sql语句中的后缀英文逗号
<update id="updateUserInfo">
    update user
    <set>
        <if test="username != null">
            username=#{username},
        </if>
        <if test="password">
            password=#{password},
        </if>
        <if test="photo">
            photo=#{photo},
        </if>
    </set>
    where id=#{id}
</update>

了解了set标签的作用,我们就想到了它可以用于信息的修改的需求,当我们不知道用户究竟要修改某个表中的那个字段时,可以通过set标签结合前端传递的参数来动态的组合sql语句中set语句块的值,实现动态信息的修改。老规矩,我们还是实现下上述需求来总结下set标签使用的规则和注意事项:

4.5 foreach-标签

当我们在遇到需要批量操作数据的场景时,MyBatis提供的foreach标签是我们的不二选择。可能有的同学和我当初想的一样,直接在服务层加一层循环挨个处理持久层前端传过来得数据集合不就可以吗?是可以,但是效率就要低很多了!接下来我们将使用foreach标签啦进行批量请求处理。我们先来看下foreach标签中需要我们手动指定得一些关键字:

  1. collection——方法中集合参数名
  2. item——进行遍历的每一个对象名
  3. open——语句块开头的字符串
  4. close——语句块结束的字符串
  5. separator——每次遍历间隔之间的字符串

例:

<delete id="deleteUserBatch">
    delete from user where id in
    <foreach collection="ids" open="(" close=")" item="id" separator=",">
        #{id}
    </foreach>
</delete>

下面还是老规矩,我们借助foreach来实现批量删除用户的操作总结以下foreach标签的使用及其注意事项:

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

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

相关文章

ACL2022 | 大模型微调哪家好?小孩子才做选择,成年人当然是全都要

一、概述 title&#xff1a;UNIPELT: A Unified Framework for Parameter-Efficient Language Model Tuning 论文地址&#xff1a;https://arxiv.org/abs/2110.07577 代码&#xff1a;GitHub - morningmoni/UniPELT: Code for paper "UniPELT: A Unified Framework for…

Java程序设计入门教程--浮点类型

情形 在Java中&#xff0c;Java提供了两种浮点型数据&#xff0c;单精度float和双精度double。 格式 一般情况下实型常量以如下形式表示&#xff1a; 0.123, 1.23, 123.0 等等表示双精度数&#xff1b; 123.4f, 145.67F, 0.65431f 等等表示单精度数。 当表示的数字比较…

零代码平台如何助力企业数字化,零代码会把IT人员淘汰掉吗

据研究&#xff0c;国内企业超过 70% 以上的业务管理需求得不到 IT 排期。 由于爆发的业务需求无法被满足&#xff0c;企业的数字化转型过程中充满着危险的 IT 失能陷阱。 01 IT面临的信息化现状 业务管理需求爆发&#xff1a; 在经济增速下行趋势下&#xff0c;企业面临更…

【Java8新特性--->异步处理】CompletableFuture

一、引入 假设一个商品详情页需要以下操作&#xff1a; 查询展示商品的基本信息耗时&#xff1a;0.5s 查询展示商品的销售信息耗时&#xff1a;0.7s 查询展示商品的图片信息耗时&#xff1a;1s 查询展示商品销售属性耗时&#xff1a;0.3s 查询展示商品规格属性耗时&#xff1a…

JVM--解析运行期优化与JIT编译器

本篇博客&#xff0c;我们来谈一谈JVM&#xff08;HotSpot&#xff09;为了提高Java程序的运行效率&#xff0c;都实现了哪些激动人心的技术&#xff5e; 1 JIT编译器的引入 首先我们这篇文章中所说的编译器都是指JVM的组成部分之一---即时编译器&#xff08;JIT&#xff09;…

《三》Git 中的本地仓库

初始化本地 Git 仓库&#xff1a; 通过 git init 初始化&#xff0c;可以把当前目录变成了 Git 管理的本地仓库。目前仅仅是做了一个初始化仓库的操作&#xff0c;项目里的文件还没有被跟踪。 在当前目录下会出现一个名为 .git 的目录&#xff0c;这些文件是 Git 仓库的核心。…

每天一个面试题之==和equals的区别是什么?

&#xff1d;&#xff1d;和equals的区别是什么&#xff1f; ""是一个关系运算符&#xff0c;关系运算符可以用来进行数据和数据之间的比较&#xff0c;而在java中数据类型大致可以分为两大类分别是基本数据类型和引用数据类型。 基本数据类型包含 byte&#xff0c…

React学习笔记八-受控与非受控组件

此文章是本人在学习React的时候&#xff0c;写下的学习笔记&#xff0c;在此纪录和分享。此为第八篇&#xff0c;主要介绍非受控组件与受控组件。 目录 1.非受控组件 1.1表单提交案例 1.2案例的总结 2.受控组件 2.1受控组件案例 2.1受控案例总结 1.非受控组件 1.1表单提…

基于LLMs的多模态大模型(Flamingo, BLIP-2,KOSMOS-1,ScienceQA)

前一篇博客已经整理了不训练视觉模型的文章们&#xff1a; 基于LLMs的多模态大模型&#xff08;Visual ChatGPT&#xff0c;PICa&#xff0c;MM-REACT&#xff0c;MAGIC&#xff09; 本篇文章将介绍一些需要训练视觉编码器来适配多模态大模型的工作们&#xff0c;这也是目前最…

QT桌面项目(状态栏和导航栏设置)

文章目录 前言一、状态栏二、导航栏三、同时添加状态栏和导航栏总结 前言 为了和我们这个项目做的更加真实&#xff0c;这里为我们的项目添加上状态栏和导航栏让他变成更加接近手机的桌面效果。 一、状态栏 这个状态栏就是显示时间和wifi状态&#xff0c;电池电量的&#xf…

9秒被骗132万元,AI换脸骗术,如何防范?

5月22日&#xff0c;安徽安庆的何先生接到熟人视频电话&#xff0c;让他帮忙转一笔账&#xff0c;但在9秒之后&#xff0c;对方却以“在开会”为由&#xff0c;迅速挂断了电话&#xff0c;还称“微信和电话不能说&#xff0c;加一下QQ”。“因为打了视频电话&#xff0c;又是熟…

数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)

目录 邻接矩阵 图节点的结构 创建并初始化 插入边 完整的图的建立 邻接表 图节点的结构 创建并初始化 插入边 完整的图的建立 邻接矩阵 图节点的结构 #include <stdio.h> #include <stdlib.h>#define MaxVertexNum 100 // 最大顶点数typedef int Wei…

Maven介绍与安装和配置

目录 Maven 简介 约定优于配置 Maven 特点 Maven 安装与配置 Maven 下载 配置 Maven 环境变量 Maven 简介 Maven 是一款基于 Java 平台的项目管理和整合工具&#xff0c;它将项目的开发和管理过程抽象成一个项目对象模型&#xff08;POM&#xff09;。开发人员只需要做一…

C语言结构体

C语言结构体 前言1. 结构体的声明1.1 结构体的基础知识1.2 结构体声明1.3 结构体成员的类型1.4 结构体变量的定义和初始化 2. 结构体成员的访问2.1 结构体变量访问成员2.2 结构体指针访问指针变量的成员 3. 结构体传参4. 结尾 前言 C语言结构体是一种自定义数据类型&#xff0…

vite-plugin-pwa配置详解

vite-plugin-pwa配置详解 前提&#xff1a;前端域名和后端服务域名相同时&#xff0c;用window.open新开页面下载或者导出文件&#xff0c;项目中导出和下载功能失效&#xff0c;原因是&#xff0c;域名相同走缓存 实现service worker离线缓存以前需要自己编写sw.js文件内容&…

基于SpringBoot+Vue的闲一品交易平台设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

MT4电脑版交易软件使用技巧有哪些?

MT4交易软件作为连接券商平台与投资者之间的纽带&#xff0c;不仅是外汇金融机构的首选交易平台&#xff0c;也因其显著的优势成为了外汇投资者进行网上交易的重要平台。而MT4交易软件又分为电脑版和手机版&#xff0c;因为大多数投资者进行外汇投资时使用的是MT4电脑版软件&am…

Gradio的web界面演示与交互机器学习模型,接口自动刷新或连续刷新数据流《5》

通过在接口中设置liveTrue&#xff0c;可以使接口自动刷新。现在&#xff0c;一旦用户输入发生变化&#xff0c;界面就会重新计算。依然使用计算器的示例&#xff1a; 实时接口 import gradio as grdef calculator(num1, operation, num2):if operation "add":ret…

浏览器原理+跨域+解决方案

原网址&#xff1a;浏览器部分笔记_浏览器不同窗口cookie共享吗_JackieChan_的博客-CSDN博客 一、浏览器存储对象 1.cookie cookie是一种纯文本文件&#xff0c;大小只有4kb&#xff0c;每次发送非跨域html请求时都会自动携带。特性如下&#xff1a; cookie一旦创建&#xff…

华为开源自研AI框架昇思MindSpore应用案例:Pix2Pix实现图像转换

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 在实际应用场景中&#xff0c;由于训练数据集不足&#xff0c;所以很少有人会从头开始训练整个网络。普遍的做法是&#xff0c;在一个非常大的基础数据集上训练得到一个预训练模型&#xff0c;然后使用该模…