【JavaEE】Spring(6):Mybatis(下)

embedded/2025/2/6 10:55:48/


一、Mybatis XML配置文件

Mybatis开发有两种方式:

  1. 注解
  2. XML

之前讲解了注解的方式,接下来学习XML的方式

1.1 配置数据库连接和Mybatis

直接在配置文件中配置即可:

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
mybatis:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath:mapper/**Mapper.xml #配置xml文件的路径

UserInfoXMLMapper.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.example.demo.mapper.UserInfoXMLMapper"><select id="queryAllUser" resultType="com.example.demo.model.UserInfo">select username,`password`, age, gender, phone from userinfo</select></mapper>

测试代码:

@Test
void queryAllUser() {userInfoMapper.queryAllUser();
}

1.2 增(Insert)

xml文件:

<insert id="insertUser">insert into userinfo (username, `password`, age, gender, phone) values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>

UserInfoXMLMapper接口:

Integer insertUser(UserInfo userInfo);

返回结果是影响的行数

返回自增id:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into userinfo (username, `password`, age, gender, phone) values (#{username}, #{password}, #{age},#{gender},#{phone})
</insert>

1.3 删(Delete)

xml文件:

<delete id="deleteUser">delete from userinfo where id = #{id}
</delete>

1.4 改(Update)

xml文件:

<update id="updateUser">update userinfo set username=#{username} where id=#{id}
</update>

1.5 查(Select)

在使用注解查询所有用户时,会遇到有属性没有被赋值的情况,我们的解决方案分别为:起别名、结果映射、 列名驼峰式命名

现在使用xml文件,解决方案仍然是这三个,其中第1个和第3个和注解的方式一样,这里主要讲解以下结果映射

<resultMap id="BaseMap" type="com.example.demo.model.UserInfo"><id column="id" property="id"></id><result column="delete_flag" property="deleteFlag"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result>
</resultMap>
<select id="queryAllUser" resultType="com.example.demo.model.UserInfo" resultMap="BaseMap">select id, username,`password`, age, gender, phone, delete_flag, create_time, update_time from userinfo
</select>

二、#{} 和 ${}的区别

#{}和${}都可以用来赋值,我们之前都用的#{},接下来看以下这两个的区别

1. 赋值的是Integer类型

首先是#{}

<select id="selectUserById" resultType="com.example.demo.model.UserInfo">select username, password, age, gender, phone from userinfo where id = #{id}
</select>

观察日志:

我们输入的参数并没有拼接到SQL语句中,而是用?作为占位符,我们称这种SQL为预编译型SQL

现在改成${}

<select id="selectUserById" resultType="com.example.demo.model.UserInfo">select username, password, age, gender, phone from userinfo where id = ${id}
</select>

此时我们输入的参数拼接到了SQL语句中

2. 赋值的是String类型

首先是#{}

<select id="selectUserByName" resultType="com.example.demo.model.UserInfo">select username, password, age, gender, phone from userinfo where username = #{username}
</select>

改为${}

<select id="selectUserByName" resultType="com.example.demo.model.UserInfo">select username, password, age, gender, phone from userinfo where username = ${username}
</select>

由于SQL语法中,字符串类型需要加上单引号,将参数直接拼接到SQL语句中是没有加单引号的,因此会报错

所以要在xml中手动加上单引号

${}存在SQL注入问题

SQL注入:通过输入的数据来修改事先定义好的SQL语句,以达到执行代码共计服务器的方式

举例:查询名字为 lisi 的用户信息,正常情况要手动加上单引号

我们输入lisi后,就可查到他的信息,但如果将输入改为 'or 1 = '1 ,将该参数拼接到SQL语句后:

可以看到通过这个查询条件可以查询到所有用户的信息

如果将密码验证的代码简单的写成 password = '${password}',此时如果密码写 'or 1 = '1,就可以直接登录成功

2.1 排序功能

${}存在SQL注入问题,但也不是一点没用,其中排序就需要用到${}

<select id="selectAllUserBySort" resultType="com.example.demo.model.UserInfo">select username, password, age, gender, phone from userinfo order by id ${sort}
</select>

执行测试代码

@Test
void selectAllUserBySort() {userInfoXMLMapper.selectAllUserBySort("desc");
}

如果使用#{},由于参数类型为String,在查询时,desc前后会自动加上单引号,但排序并不需要单引号,所以会出错

2.2 like 查询

like 使用#{}报错

@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time from userinfo where username like '%#{key}%' ")
List<UserInfo> queryAllUserByLike(String key);

把 #{} 改成 ${} 可以正确查出来,但是 ${} 存在SQL注⼊的问题,所以不能直接使⽤ ${}
解决方法:使⽤ mysql的内置函数concat()来处理,实现代码如下:

@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time from userinfo where username like concat('%',#{key},'%')")
List<UserInfo> queryAllUserByLike(String key);

三、动态SQL

1.1 <if>标签

<if>标签的作用:动态拼接

<insert id="insertUserByCondition">insert into userinfo (username,`password`,age,<if test="gender != null">gender,</if>phone)values (#{username},#{age},<if test="gender != null">#{gender},</if>#{phone})
</insert>

上述代码:如果gender不为空,则会将其拼接到SQL语句中(也就是我们在传参时,传了gender这个参数)

1.2 <trim>标签

<trim>标签的作用:添加或删除前缀和后缀

刚才我们只有一个选填字段,事实上可能有多个:

<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>

trim标签中:

  • prefix:以prefix的值作为整个语句块的前缀
  • suffix:以suffix的值作为整个语句块的后缀
  • prefixOverrides:表示整个语句块要去除的前缀
  • suffixOverrides:表示整个语句块要去除的后缀,在上述代码中最后拼接的字段可能结尾带有逗号,所以加上suffixOverrides

1.3 <where>标签

看下图,有时条件也需要动态拼接:

<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>

<where>标签还有两个作用:

  1. 如果没有判断条件,where会自动去除
  2. 如果第一个条件有前缀and或or,<where>标签也会自动去除

1.4 <set>标签

<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>

<set>标签可以自动删除额外的逗号

1.5 <foreach>标签

<foreach>标签的作用:对集合进行遍历

批量删除:

Integer deleteByIds(List<Integer> ids);
<delete id="deleteByIds">delete from userinfowhere id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>
</delete>
  • collection:绑定方法参数中的集合,也就是要遍历的集合
  • item:遍历的每一个对象
  • separator:每次遍历之间间隔的字符串
  • open:整个语句块开头的字符串
  • close:整个语句块结尾的字符串

1.6 <include>标签

在xml文件中配置的SQL有许多重复的片段

解决方法:将重复的sql片段提取出来放在<sql>标签,然后通过<include>标签复用

<sql id="allColumn">username, password, age, gender, phone
</sql>
<select id="selectUserById" resultType="com.example.demo.model.UserInfo">select<include refid="allColumn"></include>from userinfo where id = ${id}
</select>

🙉本篇文章到此结束


http://www.ppmy.cn/embedded/160004.html

相关文章

基于单片机的智能感控杆设计(论文+源码)

2.1功能设计 本次以智能感控杆设计为题&#xff0c;智能感控杆是一种可以应用在多种场合的设备&#xff0c;可以极大的节约人类的精力和时间。在此将其主要功能设计如下&#xff1a; 1.LCD1602液晶显示当前感控杆状态开启/关闭&#xff0c;显示当前模式手动/自动&#xff1b…

网易有道开源 “子曰 - o1” 推理模型

网易有道开源的 “子曰 - o1” 推理模型支持消费级显卡&#xff0c;主要通过以下技术实现&#xff1a; 轻量级模型设计&#xff1a;“子曰 - o1” 采用 14B 参数规模&#xff0c;相比许多对硬件配置要求高的大型推理模型&#xff0c;选择了较小的参数规模&#xff0c;从基础上降…

Linux 安装 RabbitMQ

Linux下安装RabbitMQ 1 、获取安装包 # 地址 https://github.com/rabbitmq/erlang-rpm/releases/download/v21.3.8.9/erlang-21.3.8.9-1.el7.x86_64.rpm erlang-21.3.8.9-1.el7.x86_64.rpmsocat-1.7.3.2-1.el6.lux.x86_64.rpm# 地址 https://github.com/rabbitmq/rabbitmq-se…

Maven(Ⅱ):依赖范围,依赖传递,依赖阻断,可选依赖

1. Maven 依赖范围 概念 依赖范围&#xff08;Dependency Scope&#xff09;用于控制依赖在不同构建阶段的可见性和可用性。Maven 定义了几种不同的依赖范围&#xff0c;每种范围都有其特定的使用场景。 常见依赖范围及用途 compile&#xff1a;默认的依赖范围&#xff0c;…

【AI知识点】特征编码(Feature Encoding)

特征编码 是将数据集中的分类特征&#xff08;Categorical Features&#xff09;转换为数值特征&#xff08;Numerical Features&#xff09;的过程。分类特征是机器学习模型&#xff08;尤其是数值模型&#xff0c;如线性回归、支持向量机等&#xff09;无法直接处理的数据类型…

图像特征点提取与匹配

引入 视觉里程计根据两帧图像确定机器人的位姿变化。视觉里程计的算法主要分为两个大类&#xff1a;特征点法和直接法。特征点法长久以来&#xff08;直到现在&#xff09;被认为是视觉里程计的主流方法。而特征点法首先需要提取特征点并进行匹配。 1. 特征点 1.1特征点的定义…

Spring Boot统一异常拦截实践指南

Spring Boot统一异常拦截实践指南 一、为什么需要统一异常处理 在Web应用开发中&#xff0c;异常处理是保证系统健壮性和用户体验的重要环节。传统开发模式中常见的痛点包括&#xff1a; 异常处理逻辑分散在各个Controller中错误响应格式不统一敏感异常信息直接暴露给客户端…

【C语言】自定义类型讲解

文章目录 一、前言二、结构体2.1 概念2.2 定义2.2.1 通常情况下的定义2.2.2 匿名结构体 2.3 结构体的自引用和嵌套2.4 结构体变量的定义与初始化2.5 结构体的内存对齐2.6 结构体传参2.7 结构体实现位段 三、枚举3.1 概念3.2 定义3.3 枚举的优点3.3.1 提高代码的可读性3.3.2 防止…