05、MyBatis

一、简介

MyBatis它是一款优秀的持久层框架,它支持自定义SQL、存储过程及高级映射。不像Hibernate等一些全自动框架,对于关键的SQL部分可以交由程序自己编写而不是自动生成,从而提高了灵活性。

二、基础使用示例

基础依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>3.0.3</version><scope>test</scope>
</dependency>

数据库及相关表数据

CREATE DATABASE `mybatis-example`;USE `mybatis-example`;CREATE TABLE `t_emp`(id INT AUTO_INCREMENT,emp_name CHAR(100),age INT,emp_salary DOUBLE(10,5),PRIMARY KEY(id)
);INSERT INTO `t_emp`(emp_name,age,emp_salary) VALUES("tom",18,200.33);
INSERT INTO `t_emp`(emp_name,age,emp_salary) VALUES("jerry",19,666.66);
INSERT INTO `t_emp`(emp_name,age,emp_salary) VALUES("andy",20,777.77);

基础配置

我们需要操作数据库至少要配置数据库连接的url,账号,密码信息

# 数据库配置信息
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-example
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

对于数据表的JavaBean

@Data
public class Emp {private Integer id;private String empName;private Integer age;private Double empSalary;
}

操作数据库的mapper接口

@Mapper
public interface EmpMapper {Emp getEmpById(Integer id);
}

我们使用MyBatis后,对于这个mapper接口的实现我们不再写了,而我们一般为每个mapper接口提供一个xml文件,在这个文件中配置指定的sql。

注意:接口上的注解@Mapper是MyBatis提供的!!

sql映射文件

<?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.xiaoxie.mybatis.dao.EmpMapper"></mapper>

这个文件可以借助相关的插件来生成。

其中namespace属性指定了接口的全类名,这样的话这个sql映射文件就与具体的接口进行了关联。

我们要在映射文件中实现接口中对应方法的sql,最终如下:

<?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" >
<!-- namespace写mapper接口的全类名,代表这个xml文件与这个指定的mapper接口绑定 -->
<mapper namespace="com.xiaoxie.mybatis.dao.EmpMapper"><!-- Emp getEmpById(Integer id); --><!--select标签代表一次查询id:表示对应绑定的mapper接口中的方法名resultType:表示查询的结果类型sql语句中写了字段别名是为了保证查询结果的列名与我们实体的名称保持一致--><select id="getEmpById" resultType="com.xiaoxie.mybatis.bean.Emp">selectid,emp_name as empName,age,emp_salary as empSalaryfrom t_emp where id = #{id}</select>
</mapper>

配置文件中指定sql映射文件位置

# mybatis配置
# xml的sql映射文件位置
mybatis.mapper-locations=classpath:mapper/**.xml

以上步骤则基本的集成使用就完成,其实现步骤总结如下:

  1. 导入mybatis相关依赖
  2. 配置数据源的连接信息,这一步与使用不使用mybaits无关,要操作数据库都是需要的
  3. 编写JavaBean对应数据库的表模型
  4. 编写mapper接口,用它来对应一个sql映射文件,注意:在mybaits当中mapper接口使用@Mapper注解标注而不是Spring中的@Repository
  5. 在classpath路径下新建sql映射文件,这个映射文件最终与mapper接口对应
  6. 在配置文件中配置sql映射文件的位置

基础搭建细节说明

  • 每个mapper接口要对应一个sql映射文件
  • mapper接口的实现类由是一个由MyBatis自动生成的代理类来实现的,容器中mybatis为每个mapper接口会创建动态代理的实现
  • sql映射文件中namespace需要绑定mapper接口的全类名
  • 在sql映射文件中select,insert,update,delete标签分别对应的是要做的查询,新增,更新,删除动作。
    • 标签中的id属性要与mapper接口中的方法名对应上
    • 如果方法有返回值必须在标签中指定resultType,其指定的类型要与返回值匹配
    • 标签体中则是具体要执行的sql
    • 对于复杂的结果封装,需要指定resultMap规则

添加运行sql日志打印

在配置文件中添加如下配置

# 日志配置
# 指定具体包名日志级别
logging.level.com.xiaoxie.mybatis.mapper=debug

新增时获取数据库自增id值

注意,当我们新增数据后,不应该依赖新增完后再做查询来获取,因为这种方式对于单线程下查可能是没有问题的,多线程下我们是不知道具体要查哪一条记录的(除非我们新增的数据一定会有一字段保持记录的唯一性),如果我们只是查ID最大值这个时候可能有别人写进来数据,这时查的就错了!!

如果我们要获取新增成功的id,可以按如下操作:

  • 在sql映射文件中的相关insert标签中新增一个属性:useGeneratedKeys="true"
    •  这个表示告诉mybatis,这个新增语句会使用自动生成的主键
  • 再在这个标签中新增一个属性:keyProperty="id"
    • 表示自动生成的主键值对应的JavaBean属性值是id,这样的话最终自动把自动生成的主键值封装到JavaBean的id属性上

开启驼峰命名

我们一般在数据库中使用下划线_来分隔字段名的多个部分,而在JavaBean属性中使用驼峰命名,这样就会导致我们数据库的字段名与JavaBean的属性名对应不上,对于这种对应不上我们前面的解决方式是在sql映射文件中使用别名的方式,但是写别名还是比较麻烦的,所以mybatis提供了一个配置可以完成_转驼峰的自动映射

# 开启驼峰命名自动映射
mybatis.configuration.map-underscore-to-camel-case=true

三、关于mybaits的参数传递

在前面基础使用示例中查询我们传入的id参数我们使用的是#{}的方式来占位表示的,其实还有${}。

#{}与${}

#{}

底层使用的是PreparedStatement方式,SQL预编译后设置参数,无sql注入攻击风险

${}

底层使用statement方式,SQL没有预编译,直接拼接参数,它是会有sql注入风险的

使用建议:所有参数尽量都使用#{},对于动态表名的位置才用${},因为表名那个地方是没有办法通过#{}使用占位符赋值进去的

注意:但凡是使用了${}的业务,一定要注意SQL注入风险,要自编写防SQL注入攻击代码!

#{}单个参数取值

单个参数 - 普通类型

取值的方式:#{变量名}

示例如下:

Emp getEmp(Integer id);
<!-- 当只有一个参数的时候这里#{}中不管写什么都是表示取那个唯一参数的值,建议写的时候保持与参数名一致 -->
<select id="getEmp" resultType="com.xiaoxie.mybatis.bean.Emp">select * from t_emp where id = #{abc}
</select>

单个参数 - List类型

取值方式:#{变量名[0]}

示例如下:

Emp getEmp02(List<Integer> ids);
<select id="getEmp02" resultType="com.xiaoxie.mybatis.bean.Emp">select * from t_emp where id = #{ids[1]}
</select>

单个参数 - 对象类型

取值方式:#{对象中的属性名}

示例如下:

void addEmp(Emp emp);
<insert id="addEmp">insert into t_emp(emp_name,age,emp_salary) values(#{empName},#{age},#{empSalary})
</insert>

单个参数 - Map类型

取值方式:#{map中的key}

示例如下:

void addEmp02(Map<String, Object> m);
<insert id="addEmp02">insert into t_emp(emp_name,age,emp_salary) values(#{name},#{age},#{salary})
</insert>

多参数@Param注解每个参数名字

在新版的MyBatis中是支持多个参数的方法直接在sql映射文件中使用#{参数名}来取得对应的参数值的。但是这个特性在老版本中是不支持的,需要在方法参数中使用@Param注解告诉MyBatis参数的名称是什么

如下所示:

Emp getEmpByIdAndName(@Param("id") Integer id, @Param("empName") String empName);
<!--新版本中支持多个参数情况下,直接使用#{参数名}以上特性在老版本中不支持,,需要在方法参数上使用@Param注解告诉Mybatis,参数名称-->
<select id="getEmpByIdAndName" resultType="com.xiaoxie.mybatis.bean.Emp">select * from t_emp where id = #{id} and emp_name = #{empName}
</select>

建议在多参数时推荐使用@Param注解指定参数名。原因如下:

  1. 直接使用参数名这个特性必须要升级使用新版本Mybatis
  2. 使用@Param注解指定参数名这样使用时会更加明确

示例如下:

Emp getEmpTest(@Param("id") Integer id,@Param("m") Map<String,Object> m,@Param("ids") List<Integer> ids,@Param("e") Emp e);
<select id="getEmpTest" resultType="com.xiaoxie.mybatis.bean.Emp">select * from t_emp where id=#{id}and emp_name = #{m.name}and age=#

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

overleaf中文生僻字显示不正确,显示双线F

我是不想换全文字体的&#xff0c;只是一个生僻字显示不出来&#xff0c;就想要像word一样&#xff0c;把这个生僻字用包含这个生僻字的字体来显示就好了。 解决步骤&#xff1a; 1、使用如下宏包&#xff1a; \usepackage{xeCJK} %声明宏包&#xff0c;主要用于支持在XeTeX…

音视频入门基础:MPEG2-TS专题(24)——FFmpeg源码中,显示TS流每个packet的pts、dts的实现

音视频入门基础&#xff1a;MPEG2-TS专题系列文章&#xff1a; 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;1&#xff09;——MPEG2-TS官方文档下载 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;2&#xff09;——使用FFmpeg命令生成ts文件 音视频入门基础…

Boost之log日志使用

不讲理论&#xff0c;直接上在程序中可用代码&#xff1a; 一、引入Boost模块 开发环境&#xff1a;Visual Studio 2017 Boost库版本&#xff1a;1.68.0 安装方式&#xff1a;Nuget 安装命令&#xff1a; #只安装下面几个即可 Install-package boost -version 1.68.0 Install…

QWidget应用封装为qt插件,供其他qt应用调用

在之前的文章中,有介绍通过QProcess的方式启动QWidget应用,然后将其窗口嵌入到其他的qt应用中,作为子窗口使用.这篇文章主要介绍qt插件的方式将QWidget应用的窗口封装为插件,然后作为其他Qt应用中的子窗口使用. 插件优点: 与主程序为同一个进程,免去了进程间繁琐的通信方式,…

大数据-261 实时数仓 - 业务数据库表结构 交易订单、订单产品、产品分类、商家店铺、地域组织表

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; MyBatis 更新完毕目前开始更新 Spring&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; H…

Pyside6 在 pycharm 中的配置

打开文件->设置 找到 工具->外部工具 点击 号 创建一个外部工具 QtDesigner 名称:QtDesigner 程序&#xff1a;D:\miniconda\envs\ergoAI-qt\Lib\site-packages\PySide6\designer.exe 实参&#xff1a;$FileName$ 工作目录&#xff1a;$FileDir$ PyUIC 名称&#xf…

Linux系统编程——线程

目录 一、前言 二、线程 1、线程的理解 三、线程相关的接口 1、线程的创建 2、线程的等待 3、实验 四、总结 1、线程优点 2、线程缺点 3、线程异常 4、Linux下的进程与线程对比 一、前言 之前的文章中我们已经对进程相关的概念做了认识&#xff0c;从创建进程、子进…

SD ComfyUI工作流 对人物图像进行抠图并替换背景

文章目录 人物抠图与换背景SD模型Node节点工作流程工作流下载效果展示人物抠图与换背景 此工作流旨在通过深度学习模型完成精确的人物抠图及背景替换操作。整个流程包括图像加载、遮罩生成、抠图处理、背景替换以及最终的图像优化。其核心基于 SAM(Segment Anything Model)与…

微服务-1 认识微服务

目录​​​​​​​ 1 认识微服务 1.1 单体架构 1.2 微服务 1.3 SpringCloud 2 服务拆分原则 2.1 什么时候拆 2.2 怎么拆 2.3 服务调用 3. 服务注册与发现 3.1 注册中心原理 3.2 Nacos注册中心 3.3 服务注册 3.3.1 添加依赖 3.3.2 配置Nacos 3.3.3 启动服务实例 …

02-18.python入门基础一基础算法

&#xff08;一&#xff09;排序算法 简述&#xff1a; 在 Python 中&#xff0c;有多种常用的排序算法&#xff0c;下面为你详细介绍几种常见的排序算法及其原理、实现代码、时间复杂度以及稳定性等特点&#xff0c;并对比它们适用的场景。 冒泡排序&#xff08;Bubble Sor…

深度学习blog-卷积神经网络(CNN)

卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种广泛应用于计算机视觉领域&#xff0c;如图像分类、目标检测和图像分割等任务中的深度学习模型。 1. 结构 卷积神经网络一般由以下几个主要层组成&#xff1a; 输入层&#xff1a;接收…

三维扫描在汽车/航空行业应用

三维扫描技术应用范围广泛&#xff0c;从小型精密零件到大型工业设备&#xff0c;都能实现快速、准确的测量。 通过先进三维扫描技术获取产品和物体的形面三维数据&#xff0c;建立实物的三维图档&#xff0c;满足各种实物3D模型数据获取、三维数字化展示、3D多媒体开发、三维…

【Axure视频教程】中继器表格间传值

今天教大家在Axure制作中继器表格间传值的原型模板&#xff0c;可以将一个中继器表格里的行数据传递到另外一个中继器表格里&#xff0c;包括传值按钮在中继器内部和外部两中案例。 这个原型模板是用中继器制作的&#xff0c;所以使用也很简单&#xff0c;只需要在中继器表格里…

【测试】接口测试

长期更新好文&#xff0c;建议关注收藏&#xff01; 目录 接口规范接口测试用例设计postmanRequests 复习HTTP超文本传输协议 复习cookiesession 实现方式 1.工具 如postman ,JMeter&#xff08;后者功能更全&#xff09; 2.代码 pythonrequests / javahttpclient【高级】 接…

目录 1、常用系统数据类型 1. int或integer 2. tinyint 3. decimal[(p[,s])]或numeric[(p[,s])] 4. char(n) 5. varchar(n|max) 6. datetime 2、T-SQL创建表 3、T-SQL修改表 4、T-SQL表数据的操作 4.1 插入数据 4.2 修改数据 4.3 删除数据 5、删除表 1、常用系统…

【LLM】OpenAI 的DAY12汇总和o3介绍

note o3 体现出的编程和数学能力&#xff0c;不仅达到了 AGI 的门槛&#xff0c;甚至摸到了 ASI&#xff08;超级人工智能&#xff09;的边。 Day 1&#xff1a;o1完全版&#xff0c;开场即巅峰 12天发布会的开场即是“炸场级”更新——o1完全版。相比此前的预览版本&#x…

Redis缓存知识点汇总

Redis缓存知识点汇总 请先思考如下问题 1.Redis的缓存击穿&#xff0c;穿透&#xff0c;雪崩是什么意思&#xff1f;原因和解决方案有哪些&#xff1f; 2.Redis支持宕机数据恢复&#xff0c;他的持久化方式及其原理是什么&#xff1f; 3.如何保证双写一致性&#xff0c;即如何保…

Gitlab17.7+Jenkins2.4.91实现Fastapi/Django项目持续发布版本详细操作(亲测可用)

一、gitlab设置&#xff1a; 1、进入gitlab选择主页在左侧菜单的下面点击管理员按钮。 2、选择左侧菜单的设置&#xff0c;选择网络&#xff0c;在右侧选择出站请求后选择允许来自webhooks和集成对本地网络的请求 3、webhook设置 进入你自己的项目选择左侧菜单的设置&#xff…

仓颉编程笔记1:变量函数定义,常用关键字,实际编写示例

本文就在网页版上体验一下仓颉编程&#xff0c;就先不下载它的SDK了 基本围绕着实际摸索的编程规则来写的 也没心思多看它的文档&#xff0c;写的不太明确&#xff0c;至少我是看的一知半解的 文章提供测试代码讲解、测试效果图&#xff1a; 目录 仓颉编程在线体验网址&…

Linux 文件 I/O 基础

目录 前言 一、文件描述符&#xff08;File Descriptor&#xff09; 二、打开文件&#xff08;open 函数&#xff09; 三、读取文件&#xff08;read 函数&#xff09; 四、写入文件&#xff08;write 函数&#xff09; 五、关闭文件&#xff08;close 函数&#xff09; …