八、MyBatis

news2024/9/23 5:19:05

一、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 {
    @Autowired
  private   UserMapper userMapper;

    //查询所有用户
    public List<UserInfo> queryAllUser(){
        return userMapper.queryAllUser();
    }
}

//controller层
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private 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片段

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

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

相关文章

数据结构--第七天

递归 -递归的概念 递归其实就是一种解决问题的办法&#xff0c;在C语言中&#xff1a;递归就是函数自己调用自己 -递归的思想 递归的思考方式就是把大事化小的过程 递归的递就是递推的意思&#xff0c;归就是回归的意思 &#xff08;递归是少量的代码完成大量的运算&#xff09…

数据结构(5.5_2)——并查集

逻辑结构——数据元素之间的逻辑关系 并查集&#xff1a; 并查集&#xff08;Union-Find&#xff09;是一种树型的数据结构&#xff0c;用于处理一些不交集的合并及查询问题。它支持两种操作&#xff1a; 用双亲表示存储并查集 首先将所有根节点数组值设为-1&#xff0c;其…

[Android] [解决]Bottom Navigation Views Activity工程带来的fragment底部遮盖的问题

创建了Bottom Navigation Views Activity之后&#xff0c;在fragment_home.xml&#xff0c;加了一个RecyclerView&#xff0c; 后来添加了item之后发现底部会被盖住一部分。 解决&#xff1a;在layout里面加两句&#xff1a; android:paddingBottom"?attr/actionBarSize&…

C#获取Network的相关信息

1&#xff0c;获取网络的通断。 //方法1&#xff1a;无效果&#xff0c;并不能反映当前网络通断 bool availableSystem.Windows.Forms.SystemInformation.Network//方法2&#xff1a;通过VB获取网络状态&#xff0c;可反映当前网络通断 Microsoft.VisualBasic.Devices.Network…

Qt QML 使用QPainterPath绘制弧形曲线和弧形文本

Qt并没有相关api直接绘制弧形文字&#xff0c;但提供了曲线绘制相关类&#xff0c;所以只能另辟蹊径&#xff0c;使用QPainterPath先生成曲线&#xff0c;然后通过曲线上的点来定位每个文字并draw出来。 QML具体做法为从QQuickPaintedItem继承&#xff0c;在派生类中实现paint…

Linux 系统框架分析(一)

一、linux内核结构框图 对内核结构框图有个总体的把握&#xff0c;有助于理解为什么驱动要这样写&#xff0c;为什么写的应用程序所用的C库接口能够产生这么多的事情。 框图可以看出来&#xff0c;linux系统&#xff0c;包括五个系统 一、Linux内核结构介绍 Linux 内核是操作…

【机器学习基础】线性回归

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…

Flutter 生成图表(fl_chart)

Flutter 图表 使用fl_chart 先看最终效果 实现抖音’使用管理助手’效果 需求分析&#xff1a;统计每个用户近7天每天的使用时长&#xff08;从当天往后推导&#xff0c;假设今天周二&#xff09;&#xff0c;单位为分钟或者小时&#xff0c;根据平均时长决定 技术选型&…

Python基于TensorFlow实现卷积神经网络-双向长短时记忆循环神经网络回归模型(CNN-BiLSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着深度学习技术的发展&#xff0c;尤其是卷积神经网络&#xff08;Convolutional Neural Networks, …

Android Studio 连接手机进行调试

总所周知&#xff0c;Android Studio里的虚拟手机下载后又大又难用。不如直接连手机用。本篇文章主要内容为Android Studio怎么连接手机进行程序调试。 1. 在AndroidSDK中下载google USB Driver: 2. 连接手机&#xff1a; 进入电脑设备管理器界面。并点开便携设备&#xff0c…

wakanda:1靶机渗透测试

一、靶机下载地址 https://download.vulnhub.com/wakanda/wakanda-1.ova 二、信息收集 1、主机发现 # 使用命令 nmap 192.168.222.0/24 -sn | grep -B 2 "08:00:27:ED:98:E1" 2、端口扫描 # 使用命令 nmap 192.168.222.149 -p- -sV 3、指纹识别 # 使用命令 wha…

C++相关概念和易错语法(25)(列表初始化、initializer_list)

列表初始化是C11中新增的初始化规则&#xff0c;大大增强了初始化的灵活性&#xff0c;在本篇文章中&#xff0c;我会详细讲解列表初始化的各种使用场景。 1.从C语言初始化语法开始改变——不带赋值号的初始化方式 列表初始化可以说是将C语言的一些初始化语法进行放大的结果。…

c++习题18-计算鞍点

目录 一&#xff0c;题目 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;题目 给定一个55的矩阵&#xff0c;每行只有一个最大值&#xff0c;每列只有一个最小值&#xff0c;寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素&#xff0c;它是所在行的最大值&#x…

海外短剧小程序 ,竖屏会员付费看剧系统搭建paypal,stripe对接支付功能

目录 前言&#xff1a; 一、系统功能 二、系统常见问题 总结&#xff1a; 前言&#xff1a; 在全球化的今天&#xff0c;短剧作为一种新兴的内容形式&#xff0c;正迅速赢得国际观众的心。尤其是海外市场的短剧推广&#xff0c;正成为内容创作者和营销者的新宠。本文将深入…

AWS云服务器选择最佳区域

2024年&#xff0c;随着全球云计算的持续发展和AWS在全球不断扩展的数据中心网络&#xff0c;选择合适的AWS云服务器区域成为了企业和开发者需要认真考虑的问题。九河云告诉你在做出选择之前&#xff0c;需要考虑以哪些关键因素&#xff1a; 地理位置和用户分布 选择AWS云服务…

06:【stm32】OLED模块的简单使用

OLED模块的简单使用 OLED简单的使用 OLED简单的使用 OLED驱动函数是使用B站UP江科大的。我们直接调用即可&#xff0c;是使用软件模拟I2C协议进行通信的。具体的I2C协议可查看上官嵌入式开发中的C51单片机开发。 驱动函数文件&#xff1a;通过百度网盘分享的文件&#xff1a;…

ShardingSphere之ShardingProxy集群部署

文章目录 介绍使用Zookeeper进行集群部署统一ShardingJDBC和ShardingProxy配置通过Zookeeper注册中心同步配置直接使用ShardingProxy提供的JDBC驱动读取配置文件 介绍 开发者手册 在conf/server.yaml配置文件中有下面这一段配置&#xff0c;就是关于集群部署的 mode: # typ…

JAVA 封装一个工具类,将实例的里面的空值设为对应的默认值

JAVA 封装一个工具类&#xff0c;将实例的里面的空值设为对应的默认值&#xff0c;比喻字符串类型就设为默认 "", Integer就设为0 示例代码&#xff1a; protected static void setDefaults(Object obj) {Class<?> clazz obj.getClass();Field[] fields …

如何在FreeRtos工程中添加驱动调用

前言&#xff1a;本篇笔记学习的是韦东山老师的教程&#xff0c;连接放在最后。 上篇教程图文讲解了&#xff0c;如何使用STM32CubleMX&#xff0c;进行移植FreeRtos工程&#xff0c;如果没有使用这个软件则需要自己去手动进行移植操作&#xff0c;本篇图文教程是添加驱动&…

LeetCode.3132.找出与数组相加的整数II

题目描述&#xff1a; 给你两个整数数组 nums1 和 nums2。 从 nums1 中移除两个元素&#xff0c;并且所有其他元素都与变量 x 所表示的整数相加。如果 x 为负数&#xff0c;则表现为元素值的减少。 执行上述操作后&#xff0c;nums1 和 nums2 相等 。当两个数组中包含相同…