【Java】Mybatis

MyBatis

JavaEE三层框架:表现层、业务层、持久层。

现在开始学习持久层。持久层就是负责与数据库打交道的代码。

框架:就是一个半成品软件。在框架的基础上,可以更加高效地写出代码。

1、MyBatis快速入门

1、准备工作(创建springboot工程、导入mybatis和mysql的依赖、编写实体类、编写配置类)

2、注解开发:编写接口,使用注解编写sql语句(注解开发比较简单,先使用注解开发来进行)

3、测试。

2、数据库连接池

什么是数据库连接池?

  • 数据库连接池是个容器,负责分配、管理数据库连接( Connection )

  • 它允许应用程序重复使用一个现有的数据库连接/而不是再重新建立一个

  • 释放空闲时间超过最大空闲时间的连接/来避免因为没有释放连接而引起的数据库连接遗漏

如果没有数据库连接池会怎么样?每一次连接数据库都要创建一个数据库连接,用完后需要立刻销毁连接以免造成资源浪费。

数据库连接池的优势:

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接泄漏

sun公司在Java中提供了一个数据库连接池的标准接口,之后其他公司生产了不同的数据库连接池产品。C3P0和DBCP现在基本上也已经不用了,用的是德鲁伊和追光者Hikari。追光者是springboot默认使用的连接池。

在这里插入图片描述

切换druid连接池非常方便,导入依赖然后配置文件中改一下即可。

在这里插入图片描述

3、注解开发

就是直接在接口方法上写个注解,注解里直接写sql语句就可以了。但是,注解只适合简单的语句开发,如果想要复杂的功能的话,注解开发是非常麻烦的,这时候还是使用xml文件完成sql语句的编写更好。

在接口方法上的注解有以下几类:

  • @Select

    接口方法的返回值需要是一个实体,且实体的字段必须跟表字段一致。这样一来,查询到的结果会自动封装到实体之中。如果实体字段和表字段名字不一致,封装是不会成功的。然而问题来了,Java字段命名方式是小驼峰命名,mysql字段命名方式是下划线命名,总不能为了兼容强行把Java的字段名改成下划线命名或者强行把MySQL字段名改成小驼峰命名吧?

    解决方式有多种。

    第一种就是在@Select的sql语句中用as给MySQL表字段起别名,别名跟Java的实体字段名字一致。

    第二种是使用mybatis提供的@Results注解和@Result注解进行手动映射。

    在这里插入图片描述

    **第三种方式是最方便的。**在配置文件中写入配置让mybatis开启下划线和驼峰命名的映射。

    在这里插入图片描述

    另外,在进行条件查询时,会出现问题。

    在这里插入图片描述

    方法是使用字符串拼接函数concat

    在这里插入图片描述

  • @Delete

  • @Insert

    如果想要获得插入之后的主键,可以添加一个注解,让插入之后生成的主键赋值给实体的id属性。

    在这里插入图片描述

  • @Update

接口方法之中可以传入参数,注解中对应位置使用#{}进行代替。

Java会通过反射获取到接口方法上的注解中的sql语句,然后把sql语句发送给MySQL数据库执行。MySQL数据库接收到sql语句,会先去缓存中查找是否存在这条sql语句,如果是直接执行,如果否,先进行sql语法检查,然后对sql进行优化,然后编译sql,然后把编译好的sql存入缓存以便下次执行一样的sql语句时提高性能。这种方式称为预编译sql。预编译SQL语句的过程是将SQL语句的结构和参数分离,先将SQL语句编译为一个可执行的执行计划,然后在每次执行时只需传入参数,无需重新编译,从而减少了重复解析和编译的开销。

delete from emp where id = #{id}实际上传给MySQL的是delete from emp where id = ?以及id的值。如果直接传给MySQL的语句是delete from emp where id = id,那预编译sql就不起作用了。

预编译sql可以提高性能,另外,也可以防止sql注入攻击。

sql注入攻击是怎么一回事呢?假设Java传给mysql的不是预编译sql形式的sql语句,而是一个拼接成的完整sql语句select count(*) from user where name='' and password='',以查询账号和密码进行登录操作。这时候,有人在表单中,随便写了个账号,但是密码写入'or '1'='1,传给MySQL的语句是select count(*) from user where name='fjewa;ofj' and password=''or '1'='1',这条sql语句永远会成功,用户无论是何种身份都可以登录。

预编译sql可以解决这个问题,因为它明确了where的字段只有name和password,不会有后面的or ‘1’ = ‘1’。

4、日志输出

为了更加方便查看执行什么sql语句以及执行的结果,需要查看日志。Mybatis默认是不打开日志的,需要在配置文件中进行配置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5、xml映射文件开发

注解开发虽然方便,但是只能执行简单的sql逻辑。想要执行复杂的sql逻辑,需要使用xml文件编写sql语句进行开发。xml映射文件有一些规范。

  • xml映射文件的名称与Mapper接口名称一致,并且将xml映射文件和mapper接口放置在相同包下(同包同名)。在maven项目中,最后编译之后,main包下的java和resource两个目录都会消失的。也就是说最后java和resource里面的文件都会在一个目录下。这样一来,就可以在resource下创建sql映射文件,在java里面创建接口,只要sql映射文件和接口文件的目录写成一样的,最后编译它们就会是一样的。注意,在resource下创建层次接口不能是“com.ghl”的形式,而是"com/ghl"的形式。
  • xml映射文件的namespace属性为Mapper接口全限定名一致。(方便映射)
  • xml映射文件中sql语句的id与mapper接口中的方法名一致,并保持返回类型一致。(方便映射)

xml文件长什么样呢?

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.iss.mapper.EmpMapper">
  <!--resultType:实体的全限定名,执行结果会封装到实体之中-->
  <select id="selectEmp" resultType="com.iss.entity.Emp">
    select * from emp where id = #{id}
  </select>
</mapper>

想要调用接口中的方法来执行sql语句,接口中的方法肯定是没有这样的功能的,只有xml文件中才有sql语句。所以关键在于,如何将接口中的方法与xml文件进行映射。只要按照上边的规范正确地在xml文件中写内容,当调用接口中的方法时,mybatis会自动根据接口找到对应的xml文件,然后根据id找到方法对应的sql语句。

有一款插件可以挺方便根据接口跟xml文件的映射关系进行相互定位。MybatisX

在这里插入图片描述

查询

xml映射文件中使用select标签来进行查询。这个标签的最重要的属性有两个,一个是id(用来和接口方法进行对应的),一个是resultmap(用来把查询到的数据封装进实体类的)

准备工作:

  • 首先,由于在实体对象里,字段名使用驼峰命名,但是在数据库的字段名有时候并不是使用驼峰命名,所以有时候可能数据库的字段名与实体类的驼峰命名对应不上,这样会使得数据无法完成封装。解决方法是:在映射文件里的mapper标签里写一个resultmap标签,这个resultmap标签里面主要有两种小标签id和result。id主要用来进行主键进行映射,result主要用于对普通字段进行映射。两种小标签都有两个属性,分别是column(真正的字段名)和property(实体类的驼峰命名)。写完之后把resultmap作为查询标签的属性就可以进行映射了。

    在这里插入图片描述

  • 接着,查询语句里要有参数占位符用来指代接口方法传入的参数,有两种参数占位符:#{参数名},${参数名},前一种可以用来防止sql恶意注入(黑客攻击),后一种无法防止sql注入,安全性会差一点。

  • 注意,在核心配置文件里面,datasource标签里url那里一定要设置一个参数指定utf-8字符集,不然字符串字段查询到的内容总是null

跟普通的sql查询差不多。就是可能有参数占位符存在。

要注意一点,小于号要使用转义字符来写,因为在xml文件里边,小于号被认为是标签的起始,不会被认为是小于号。使用转义字符& lt ; (这里由于markdown自动识别成小于号了所以我直接这里加了两个空格进行处理)。

动态查询/动态sql

有这么多个字段,怎么知道用户想要查询哪个字段或者想要查询哪些字段呢?当然可以把所有可能全部写一遍,但是这样如果字段太多,会显得非常愚蠢。所以可以使用一种比较好的方法:动态查询。来实现动态查询多个字段的功能。

  • 使用if标签(配合where标签使用)来实现动态查询

要实现动态查询,其实就是在每一个条件上加上一个判断,只要判断传入的参数不为空,就使用这个参数进行查询就可以了。

所以使用if标签把条件给括起来(逻辑符也要)就可以了。但是if标签有一个问题,就是如果传入的第一个参数为空,这个参数恰好在第一个条件,那么会变成 where and 字段名 = 参数2 这样的形式,这不符合sql语法要求。**可以直接在where关键字的第一个条件写上1=1,这样就不会出现这样的问题。不过mybatis提供了一个where标签,直接使用where标签来代替where关键字就不会出现问题了,**这个标签会自动处理。where标签只会在子元素有内容的情况下才会插入子句,而且会自动去除子句开头的and和or。

if标签有一个属性test,要在test里面写判断,在标签体里写查询条件。

添加、修改和删除

  • 添加

使用insert标签进行数据添加。里面直接写insert into语句进行添加就可以了。

一个小细节。如果主键是默认自增,而且在执行接口方法的时候传入了一个没有定义主键的实体对象去添加,数据库里产生了主键,然而如何知道主键是什么呢?这个问题的解决方法可以在insert标签里设置两个属性来解决。两个属性配置上,实体中的主键字段在数据库添加完毕之后就会自动被赋值。

在这里插入图片描述

  • 修改

使用update标签进行修改。

调用接口方法传入一个实体对象,会根据实体对象的主键值和实体对象中每一个对象对应的值对对应记录的值进行修改。

动态修改:如果按照上边那种方法来写的话,那么每一次必定是修改数据库表中的全部字段。如果只想要修改某一些字段的话,就可以使用动态修改。即在set关键字下方写上if标签。这里同样会有一些bug出现,所以要将set关键字换成set标签。mybatis会自动解决bug冲突。

  • 删除

**删除单条记录:**写在delete标签里面。同样地如果想要动态删除,使用where标签和if标签。

删除多条记录:

这里如果不在xml文件里实现的话,其实可以定义一个数组,将要删除的记录的主键全部放到数组里边去,然后遍历数组,将数组里的元素一个一个传入接口方法里边就行。

不过mybatis对于这个东西有一个标签可以完成删除多条记录的功能。即foreach标签。这个标签用在where后边。

foreach有三个属性,collection用于接收接口方法传入的数组,mybatis会自动把这个数组放到一个map的值里边,键是array。所以collection属性里直接写array就可以了。item属性就是要遍历的字段,写上主键字段的名称就可以了。separator属性和open和close属性都是用来规范sql语法的。因为in后要有括号,括号中的每一个字段之间要有逗号隔开。

在这里插入图片描述

两个标签:sqlinclude。这两个标签是配套使用的。

在一个xml文件中,如果出现了大量的重复sql片段,可以使用这两个标签来解决。

<select id="selectAll" resultMap="BrandResultMap">
	select id,brand_name,enterprise_name,sort,introduction,status
	from brand;
</select>
<select id="selectById" resultMap="BrandResultMap">
	select id,brand_name,enterprise_name,sort,introduction,status
	from brand
	where id = #{id};
</select>

使用这两个标签过后,会变为:

<!--id就是用来标识这段sql代码的-->
<sql id="commonSql">
    select id,brand_name,enterprise_name,sort,introduction,status
</sql>
<select id="selectAll" resultMap="BrandResultMap">
    /*把sql的id填入refid*/
    <include refid="commonSql"/>
    from brand;
</select>
<select id="selectById" resultMap="BrandResultMap">
    /*把sql的id填入refid*/
    <include refid="commonSql"/>
    from brand
    where id = #{id};
</select>

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

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

相关文章

Spring Environment 注入引起NPE问题排查

文章目录 背景原因分析1&#xff09;Spring Aware Bean 是什么&#xff1f;2&#xff09;从 Spring Bean 的生命周期入手 解决方案 背景 写业务代码遇到使用 Spring Environment 注入为 null 的情况&#xff0c;示例代码有以下两种写法&#xff0c;Environment 实例都无法注入…

华为OD机试 - 多段线数据压缩(Java JS Python C)

题目描述 下图中,每个方块代表一个像素,每个像素用其行号和列号表示。 为简化处理,多线段的走向只能是水平、竖直、斜向45度。 上图中的多线段可以用下面的坐标串表示:(2,8),(3,7),(3,6),(3,5),(4,4),(5,3),(6,2),(7,3),(8,4),(7,5)。 但可以发现,这种表示不是最简的,…

RK3568驱动指南|第八篇 设备树插件-第80章 注册attribute实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

【C++入门到精通】互斥锁 (Mutex) C++11 [ C++入门 ]

阅读导航 引言一、Mutex的简介二、Mutex的种类1. std::mutex &#xff08;基本互斥锁&#xff09;2. std::recursive_mutex &#xff08;递归互斥锁&#xff09;3. std::timed_mutex &#xff08;限时等待互斥锁&#xff09;4. std::recursive_timed_mutex &#xff08;限时等待…

【数字图像处理】实验二 图像变换

图像变换 一、实验内容&#xff1a; 1&#xff0e; 熟悉和掌握利用Matlab工具进行数字图像的读、写、显示等数字图像处理基本步骤。 2&#xff0e; 熟练掌握各种图像变换的基本原理及方法。 3&#xff0e; 能够从深刻理解图像变换&#xff0c;并能够思考拓展到一定的应用领域。…

多层负载均衡实现

1、单节点负载均衡 1&#xff09;站点层与浏览器层之间加入了一个反向代理层&#xff0c;利用高性能的nginx来做反向代理 2&#xff09;nginx将http请求分发给后端多个web-server 优点&#xff1a; 1&#xff09;DNS-server不需要动 2&#xff09;负载均衡&#xff1a;通过ngi…

OGG同步异构数据库-表字段变更重新读取异构文件测试验证

OGG同步异构数据库-表字段变更重新读取异构文件测试验证 删除前源和目标端的同步情况&#xff1a; 配置文件信息&#xff1a; 源端&#xff1a; GGSCI (ITSMdoc-236-63) 4> view param etest extract etest setenv (MYSQL_HOME“/data/mysql-5.7.26”) tranlogoptions al…

研究生课程 |《矩阵论》复习

文章目录 【一(18)】填空题【二(10)】范数证明【三(15)】矩阵函数1 计算 e A t e^{At} eAt2 求微分方程的解 【四(10)】QR分解【五(10)】Gerschgorim隔离特征值【六(15)】 A A^ A计算及求解线性方程组1 计算满秩分解2 计算 A A^ A3 判断线性方程组解是否存在 【七(15)】线性…

快速开发教务管理应用,课程表微信小程序源码

介绍 课程表微信小程序源码 快速开发教务管理应用 对接微信公众号每日课表推送 三种导入课表方式可供选择 班级课表导入 爬虫导入课表 学号导入课表

with torch.no_grad()在Pytorch中的应用

with torch.no_grad()在Pytorch中的应用 参考&#xff1a; https://blog.csdn.net/qq_24761287/article/details/129773333 https://blog.csdn.net/sazass/article/details/116668755 在学习Pytorch时&#xff0c;老遇到 with torch.no_grad()&#xff0c;搞不清其作用&#…

P2 H264码流结构分析——Annexb与MP4格式的区别 (中)

前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_Ch…

如何使用Java的GeoTools地理库计算WGS84坐标下的两个经纬度之间得距离

介绍 本章讲解如何使用Java的GeoTools地理库计算基于WGS84坐标的两点之间的距离。适用于后台服务的距离计算。 GeoTools介绍 GeoTools是开源的Java地理信息计算库。GeoServer地图引擎就是基于GeoTools库构建得地图服务,可以说非常强大。 官网地址:https://docs.geotools.o…

python/C 生成beta分布的随机数

python/C 生成beta分布的随机数 文章目录 python/C 生成beta分布的随机数前言一、beta分布理论知识二、python 生成服从beta分布的随机数三、C语言生成服从beta分布的随机数 前言 想把一个算法用C语言实现&#xff0c;其中涉及到了beta分布取随机数&#xff0c;记录一下结果 一…

【Java】网络编程-TCP回显服务器代码编写

前面我们讲了基于UDP的网络编程 UDP回显服务器 UDP字典服务器 下面我们来讲基于TCP的回显服务编写 1、服务器 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; impo…

25、新加坡南洋理工、新加坡国立大学提出FBCNet:完美融合FBCSP的CNN,EEG解码SOTA水准![抱歉老师,我太想进步了!]

前言&#xff1a; 阴阳差错&#xff0c;因工作需要&#xff0c;需要查阅有关如何将FBCSP融入CNN中的文献&#xff0c;查阅全网&#xff0c;发现只此一篇文章&#xff0c;心中大喜&#xff0c;心想作者哪家单位&#xff0c;读之&#xff0c;原来是自己大导&#xff08;新加坡工…

冬天天冷早安问候语关心话,愿我的每句话都能带给你温馨

1、送你一声问候&#xff0c;为你驱走冬日严寒&#xff0c;送你一份关怀&#xff0c;为你增添丝丝温暖&#xff0c;送你一句祝福&#xff0c;为你驱走所有不快&#xff0c;送你一份关爱&#xff0c;为你增添幸福无限&#xff0c;天虽寒了&#xff0c;我的关心犹在&#xff0c;愿…

Centos安装Docker及使用

文章目录 配置要求Centos安装Docker卸载docker&#xff08;可选&#xff09;安装docker首先需要大家虚拟机联网&#xff0c;安装yum工具然后更新本地镜像源&#xff1a;然后输入安装docker命令&#xff1a;查看docker的版本 启动docker关闭防火墙接着通过命令启动docker 配置镜…

vscode debug c++代码

需要提前写好CMakeLists.txt 在tasks.json中写好编译的步骤&#xff0c;即tasks&#xff0c;如cmake … 和make -j 在lauch.json中配置可执行文件的路径和需要执行tasks中的哪一个任务 具体步骤&#xff1a; 1.写好c代码和CMakeLists.txt 2.配置tasks.json 终端–>配置任务…

竞赛保研 基于CNN实现谣言检测 - python 深度学习 机器学习

文章目录 1 前言1.1 背景 2 数据集3 实现过程4 CNN网络实现5 模型训练部分6 模型评估7 预测结果8 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于CNN实现谣言检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&am…

Jmeter测试时遇到的各种乱码问题及解决

在Jmeter中显示乱码 遇到的问题&#xff1a;csv文件中有的用户名是中文的&#xff0c;接口使用该用户名入参时&#xff0c;查看结果树中看到&#xff0c;中文名显示为一堆乱码。 解决的方法&#xff1a; 应该是文件编码与jmeter编码不一致导致的。 1&#xff09;新建一个tx…