当前位置: 首页 > news >正文

八、MyBatis

一、MyBatis介绍

MyBatis 是持久层框架,它支持自定义 SQL、存储过程以及⾼级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置 和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.1 MyBatis功能
MyBatis 是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具
2.2 框架交互流程图
MyBatis 也是⼀个 ORM 框架, ORM(Object Relational Mapping),即对象关系映射。在面向 对象编程语言中,将关系型数据库中的数据与对象建立起映射关系,进而自动的完成数据与对象 的互相转换:
(1)将输⼊数据(即传⼊对象)+SQL 映射成原生SQL
(2)将结果集映射为返回对象,即输出对象 ORM 把数据库映射为对象:
  • 数据库表(table)—> 类(class) 
  • 记录(record,行数据)—> 对象(object) 
  • 字段(field) —> 对象的属性(attribute)
一般的 ORM 框架,会将数据库模型的每张表都映射为⼀个 Java 类。 也就是说使用MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间的转换。

二、搭建MyBatis开发环

添加MyBatis框架时要同时添加对应数据库驱动,他们总是成对存在
项目所需基本依赖
创建完SSM项目,项目中添加了Mybatis + MySQL.之后,项目启动,一定会报错!!!这是正常现象,因为没有配置数据库连接信息
2.1 注解实现Mybatis操作

yml文件配置数据库连接信息

spring:datasource:
#    user是数据库的名称url: jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&useSSL=false
#    数据库用户名username: root
#    数据库密码password: "123456"
通过注解来进行数据库的操作
(1)@Select//Mapper层
@Mapper
public interface UserMapper {//查询所有⽤⼾ @Select("select * from userinfo")public List queryAllUser();
}//service层
@Service
public class UserService {@Autowiredprivate   UserMapper userMapper;//查询所有用户public List<UserInfo> queryAllUser(){return userMapper.queryAllUser();}
}//controller层
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;//查询所有用户@RequestMapping("/queryAllUser")public List<UserInfo> queryAllUser(){return userService.queryAllUser();}
}使⽤#{} 的方式获取⽅法中的参数
public interface UserInfoMapper {@Select("select * from userinfo where id= #{id} ")UserInfo queryById(Integer id);
}
数据库中的字段名与Java中对象名字不一致时,如何配置让数据库与属性匹配?
2.2 XML实现Mybatis(前提配置Maven)
2.2.1 配置数据库连接信息
1、配置数据库连接信息
spring:datasource:
#    user是数据库的名称url: jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&useSSL=false
#    数据库用户名username: root
#    数据库密码password: "123456"driver-class-name: com.mysql.cj.jdbc.Driver
2.2.2 配置 MyBatis 映射文件位置路径
这个配置使 MyBatis 能够扫描指定目录下的所有映射文件,并将它们加载到 MyBatis 的配置中,以便在运行时使用这些映射文件中的 SQL 语句和映射规则。此处映射到当前目录的mapper目录下的所有带有·Mapper.xml的文件
声明接口
@Mapper
public interface UserXmlMapper {
//声明查询所有用户信息的接口
   public List<UserInfo> queryXmlAllUser();
}
2.2.3 xml文件实现sql语句查询

三、解决数据库字段名与java对象属性名不一致问题

如果Java属性和mysql的字段一样, mybatis会进行自动赋值,如果不一样,则不赋值
(1)起别名
(2)结果映射
使⽤ id 属性给该 Results 定义别名,使⽤ @ResultMap 注解来复⽤其他定义的 ResultMap
(3)开启驼峰命名
驼峰命名规则:abc_xyz=>abcXyz
• 表中字段名:abc_xyz
• 类中属性名:abcXyz
三、mybatis进阶
3.1 #{属性名}和${属性名}区别
当是$时,sql语句id中会被直接替换为设置的值
当是#时,sql语句中为预编译处理会被替换为?占位符
因此当 $: 如果是整数时,不受影响,当为字符串时直接为username=张三,但是sql只能识别username='张三',所以推荐使用#更安全
但在特定情况下只能使用$
比如给查询的数据排序select * from userinfo order by desc
此时传入排序规则desc/asc(逆序/顺序)必须使用 $直接替换,否则使用#会预编译处理识别成字符串加引号,这样sql识别,语句就会发生错误
#和$区别
1.$存在SQL注入的问题,会将参数作为sql的一部分,造成信息泄露等问题
2.$直接替换;#是预处理。
3. $使用注意事项:一定是可以穷举的值,在使用之前一定要对传递的值进行合法性验证(安全性验证)。

四、动态SQL

4.1 if标签
//Controller
//1、if标签
@RequestMapping("/addUserByIf")
public Integer addUserByIf(){UserInfo userInfo = new UserInfo();userInfo.setAge(11);userInfo.setPassword("ifififififfi");userInfo.setUsername("if标签测试2");return userXmlService.addUserByIf(userInfo);
}//Service
//1、if标签
public Integer addUserByIf(UserInfo userInfo) {return userXmlMapper.addUserByIf(userInfo);
}//Mapper
Integer addUserByIf(UserInfo userInfo);//xm文件
//
<insert id="addUserByIf" >insert into userinfo(username,<if test="age != null">age,</if><if test="gender != null">gender,</if>password)values(#{username},<if test="age != null">#{age},</if><if test="gender != null"> gender,</if>#{password})
</insert>
注册信息时有必填字段和非必填字段,可以使用if标签实现sql。使用if标签中的内容,如果程序中有数据则将字段执行到sql中,否则sql排除该字段

4.2 trim标签
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表 整个语句块,以suffix的值作为后缀
prefixOverrides:表 整个语句块要去除掉的前缀
suffixOverrides:表 整个语句块要去除掉的后缀
<insert id="insertUserByCondition"> INSERT INTO userinfo <trim prefix="(" suffix=")" suffixOverrides=","> <if test="username !=null"> username, </if> <if test="password !=null"> password, </if> <if test="age != null"> age, </if><if test="gender != null"> gender, </if> <if test="phone != null"> phone, </if> </trim> VALUES <trim prefix="(" suffix=")" suffixOverrides=","> <if test="username !=null"> #{username}, </if><if test="password !=null"> #{password}, </if><if test="age != null"> #{age}, </if> <if test="gender != null"> #{gender}, </if> <if test="phone != null">#{phone} </if> </trim> 
</insert>
在以上sql动态解析时,会将第⼀个部分做如下处理:
基于 prefix 配置,开始部分加上 (
基于 suffix 配置,结束部分加上 )
多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于
suffixOverrides 配置去掉最后⼀个 ,
注意 中的 username 是传⼊对象的属性

4.3 where标签
<select id="queryByCondition" resultType="com.example.demo.model.UserInfo"> select id, username, age, gender, phone, delete_flag, create_time, update_time from userinfo <where> <if test="age != null"> and age = #{age} </if> <if test="gender != null"> and gender = #{gender} </if><if test="deleteFlag != null"> and delete_flag = #{deleteFlag} </if></where> 
</select>
删除代码块最前面的and
查询条件为空时去除where关键字

4.4 set标签
<update id="updateUserByCondition"> update userinfo <set> <if test="username != null"> username = #{username}, </if><if test="age != null"> age = #{age}, </if> <if test="deleteFlag != null"> delete_flag = #{deleteFlag}, </if> </set> where id = #{id} 
</update>
动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

4.5 foreach标签
对集合进⾏遍历时可以使⽤该标签。标签有如下属性:
collection:绑定方法参数中的集合,如List,Set,Map或数组对象
item:遍历时的每⼀个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
<delete id="deleteByIds"> delete from userinfo where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> 
</delete>

4.6 sql标签与include标签
<sql id="allColumn"> id, username, age, gender, phone, delete_flag, create_time, update_time 
</sql><select id="queryAllUser" resultMap="BaseMap"> select <include refid="allColumn"></include> from userinfo 
</select>

我们可以对重复的代码⽚段进⾏抽取,将其通过 标签封装到⼀个SQL⽚段,然后再通过标签进行引用。

定义可重用的SQL片段
通过属性refid,指定包含的SQL片段

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《网络编程实战系列》(17)网络桥接模式
  • 【设计模式】一文读懂策略模式
  • 【ML】Pre-trained Language Models及其各种微调模型的实现细节和特点
  • zip压缩包的格式不标准导致C++开源unzip.cpp解压失败问题的排查
  • loginApi
  • 每天五分钟深度学习pytorch:训练神经网络模型的基本步骤
  • 【竞品分析】竞品分析报告的基本模板
  • 裁剪或填充张量(Tensor)(四维与五维)(Python代码)
  • 【Python】requests的response.text 和 urllib.request 的 response.read()的区别
  • 编程-设计模式 26:业务代表模式
  • Android11 关于三方应用获取su权限
  • 以Zed项目为例学习大型Rust项目的组织与管理
  • 数据结构----二叉树
  • Cairo库移植到安卓记录
  • 【登录扫码】--集成企业微信
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • Asm.js的简单介绍
  • Linux CTF 逆向入门
  • Linux后台研发超实用命令总结
  • spark本地环境的搭建到运行第一个spark程序
  • windows下如何用phpstorm同步测试服务器
  • 关于Flux,Vuex,Redux的思考
  • 看域名解析域名安全对SEO的影响
  • 聊聊sentinel的DegradeSlot
  • 那些被忽略的 JavaScript 数组方法细节
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 前端自动化解决方案
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 提醒我喝水chrome插件开发指南
  • 微信支付JSAPI,实测!终极方案
  •  一套莫尔斯电报听写、翻译系统
  • 硬币翻转问题,区间操作
  • 责任链模式的两种实现
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (10)STL算法之搜索(二) 二分查找
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (附源码)ssm码农论坛 毕业设计 231126
  • (七)Activiti-modeler中文支持
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET IoC 容器(三)Autofac
  • .net mvc部分视图
  • .net 生成二级域名
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .Net环境下的缓存技术介绍
  • .NET牛人应该知道些什么(2):中级.NET开发人员