【Day 9】Mybatis CURD + XML 映射 + 动态 SQL

1 Mybatis 基础操作

下面进行:增删改查——C(create)U(update)R(retrieve)D(delete)

1.1 删除(删)

根据主键 id 进行删除

注意 占位符 #{ }

返回值是删除的记录条数

测试:

可以在日志中看到 mybatis 具体的语句

预编译 SQL 的优点:

  • 性能更高
  • 更安全(防止 SQL 注入)

        SQL 注入:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法

        1 等于 1 是true,所以结果是 16,即查到了所有人,但是是大于 0 的,系统判断登录成功,可以进入系统

使用预编译 SQL:

就是使用 占位符 #{ }

Mybatis 占位符

1.2 插入(增)

在 Mapper 里面写 insert 接口方法

注意:

  • emp 的字段采用驼峰命名,而数据库的 emp 表,是用下划线命名(这样更直观)所以在填写 values 的时候,需要看清楚
  • id 不用填写,id 是自增(increment)
  • password 也不用填写,password 是默认'123456'

然后测试

如果需要拿到插入的员工的主键:

@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +"values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, now());")
public int insert(Emp emp);

1.3 更新(改)

@Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image},job=#{job}," +"entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
public void update(Emp emp);

1.4 查询(查)

@Select("select * from emp where id=#{id}")
public Emp select(Integer id);

但是注意看,后面三个是 null 值

在数据库中查询,就不是 null 值

是因为 Emp 类字段 和 数据库表属性 不一致

解决方案一:起别名

@Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptId," +" create_time createTime, update_time updateTime from emp where id=#{id}")
public Emp select(Integer id);

解决方法二:手动封装

// 解决方案二:通过 @Results,@Result 手动封装
@Results({@Result(column = "dept_id",property = "deptId"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time",property = "updateTime")})
@Select("select * from emp where id = #{id}")
public Emp select(Integer id);

解决方法三:开启 mybatis 的驼峰命名自动映射开关

a_column         =>         aColumn

开启之后,直接按原来的写:

// 解决方案三:开启 mybatis 的驼峰命名自动映射开关
@Select("select * from emp where id=#{id}")
public Emp select(Integer id);

以上三种方法都会得到正确字段:

下面是条件查询:

输入张,性别,入职日期,结果根据更新日期降序

@Select("select * from emp where name like '%${name}%' and gender = #{gender} and entrydate between #{begin} " +"and #{end} order by update_time desc")public List<Emp> selectByCondition(@Param("name") String name,@Param("gender") Short gender,@Param("begin") LocalDate begin,@Param("end") LocalDate end);

注:

  • 要正确地映射,使用注解@Parm
  • 而且 name 是 ${name}

另:由于 name 使用了 ${name},这不是预编译 SQL,会导致性能差,SQL 注入

解决办法:

使用 MySQL 自带的 concat 方法,进行字符串拼接

2 XML 映射文件

Mybatis 操作数据库有两种方法

  • 注解
  • XML 映射文件

 注意创建文件夹的名字

XML 文件里面的配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.EmpMapper"></mapper>

2.1 MybatisX

IDEA 插件,用来简化 mybatis 

2.2 到底用注解还是 XML

3 动态 SQL(终于讲到这一点了)

        为什么说“终于讲到这一点了”,

        因为之前我就有个疑问,如果我只想查一下姓张的人,我不指定性别和入职日期,以前那个代码就查询不了:

@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin} " +"and #{end} order by update_time desc")
public List<Emp> selectByCondition(@Param("name") String name,@Param("gender") Short gender,@Param("begin") LocalDate begin,@Param("end") LocalDate end);

动态 SQL:随着用户的输入或外部条件的变化而变化的SQL语句,我们称为动态 SQL

Mybatis 中有很多动态 SQL 标签

  • <if>
  • <foreach>
  • <sql><include>

3.1 <if>

在 XML 里面去写

注意:and 要在新的一行里面写,之前我在行尾写,那样不行

<mapper namespace="com.example.mapper.EmpMapper"><select id="selectByCondition" resultType="com.example.pojo.Emp">select *from empwhere<if test="name!=null">name like concat('%',#{name},'%')</if><if test="gender!=null">and gender = #{gender}</if><if test="begin!=null"><if test="end!=null">and entrydate between #{begin} and #{end}</if></if>order by update_time desc</select>
</mapper>

这样就可以查到只姓张的人了

注意:判断入职日期,也可以在中间用 and,就不用像我那样两层 if:

<if test="begin!=null and end!=null"></if>

但是对于只输入性别,其他三个字段都为 null,又报错

@Testpublic void testSelectGender(){List<Emp> empList = empMapper.selectByCondition(null, (short) 1, null, null);empList.stream().forEach(System.out::println);}

因为 name 为 null,在 XML 里面跳过name,直接到 gender,where 直接以 and 开头了,

解决办法:把 where 改为 <where>

标签版的 where 可以自动去掉 and 或者 or,并且在条件都不成立的情况下去掉 where(真的智能)

3.2 关于之前 update 的动态 SQL

之前的 update 存在问题

正常应该是传过来什么字段,就更新什么字段,没有就不变

但是现在是没有字段的情况下,直接设置为 null

解决:使用动态 SQL

就不用注解了,把之前代码注释掉

    // 这段代码有问题,现在不用了,在 XML 重写了
//    @Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image},job=#{job}," +
//            "entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
public void update(Emp emp);

在 XML 里加 

<update id="update"> #  更新不需要返回什么东西,所以没有属性 resultTypeupdate empset<if test="username!=null">username=#{username}</if><if test="name!=null">,name=#{name}</if><if test="gender!=null">,gender=#{gender}</if><if test="image!=null">,image=#{image}</if><if test="job!=null">,job = #{job},</if><if test="entrydate!=null">,entrydate=#{entrydate}</if><if test="deptId!=null">,dept_id=#{deptId}</if><if test="createTime!=null">,create_time=#{createTime}</if><if test="updateTime!=null">,update_time = now()</if>where id=#{id}</update>

 这一次我们把第20个人,张测试,把他性别改成女,其他的字段不变:

 还是像上次一样,set 也有标签版本的 <set>

用标签版本的 set 更好

3.3 <foreach>

批量删除:

 MySQL 语句:

delete from emp where id in (18,19,20);

现在是 Mybatis:

EmpMapper 里面添加:

 然后alt + 回车在 XML <mapper>里面写

<!--批量删除员工 delete from emp where id in(18,19,20)collection 遍历的集合item 遍历的元素separator 分隔符open 遍历开始前拼接的 SQL 片段close 遍历结束后拼接的 SQL 片段
--><delete id="deleteByIds">delete from emp where id in<foreach collection="list" item="id" separator="," open="(" close=")">#{id}</foreach></delete>

 测试(没有 17 是因为之前删除过)

3.4 <sql><include>

这两个标签解决代码复用

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

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

相关文章

项目管理系统(PMS):一文扫盲,再也不用担心质量和延期了。

一、什么是PMS系统 项目管理系统&#xff08;PMS&#xff09;是一种软件工具或平台&#xff0c;用于帮助组织和团队有效地规划、执行和监控项目。PMS系统提供了一系列功能和工具&#xff0c;以支持项目管理的各个方面&#xff0c;包括项目计划、进度跟踪、资源管理、任务分配、…

Android Studio 报错:AVD Pixel_3a_API_30_x86 is already running

在我的Android Studio和虚拟机运行时&#xff0c;我的电脑不小心关机了&#xff0c;在启动后再次打开Android Studio并运行虚拟机时发现报错。 Error while waiting for device: AVD Pixel_3a_API_30_x86 is already running. If that is not the case, delete the files at C…

【Docker】Docker 实践(一):在 Docker 中部署第一个应用

Docker 实践&#xff08;一&#xff09;&#xff1a;在 Docker 中部署第一个应用 1.使用 YUM 方式安装 Docker2.验证 Docker 环境3.在 Docker 中部署第一个应用3.1 小插曲&#xff1a;docker pull 报 missing signature key 错误3.2 重新安装 Nginx 1.使用 YUM 方式安装 Docker…

C++链表操作入门

数据结构基础&#xff1a;链表操作入门 数据结构基础&#xff1a;链表操作入门链表的基本概念链表的基本操作输出链表插入节点删除节点查找值 完整的链表操作示例结语 数据结构基础&#xff1a;链表操作入门 在计算机科学中&#xff0c;数据结构是组织和存储数据的方式&#x…

Redis高级篇详细讲解

0.今日菜单 Redis持久化【理解】 Redis主从 Redis哨兵 Redis分片集群【运维】 单点Redis的问题 数据丢失问题&#xff1a;Redis是内存存储&#xff0c;服务重启可能会丢失数据 并发能力问题&#xff1a;单节点Redis并发能力虽然不错&#xff0c;但也无法满足如618这样的高…

构建安全高效的前端权限控制系统

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

insightface 环境配置

首先创建续集环境&#xff1a; conda create -n insightface3 python3.8 然后打开此虚拟环境&#xff1a;conda activate insightface3 然后安装&#xff1a; pip install insightface 再安装&#xff1a;pip install onnxruntime-gpu 就可以了

OV SSL证书申请指南——六步轻松搞定

OV证书的申请流程如下&#xff1a; 一 确定申请渠道 根据自己的品牌偏好&#xff0c;选择一个证书服务商&#xff0c;这里推荐JoySSL,作为国产服务商&#xff0c;除了提供Digicert、Sectigo、Geotrust、Globalsign等国际品牌证书外&#xff0c;还拥有自主品牌OV证书。在JoySSL…

微信小程序:8.WXSS

WXSS和CSS的关系 WXSS具有CSS大部分特性&#xff0c;同时&#xff0c;WXSS还对CSS进行扩充以及修改&#xff0c;适应微信小程序的开发。 与CSS相比&#xff0c;WXSS扩展的特性有&#xff1a; rpx尺寸单位imprt样式导入 rpx尺寸单位 rpx是微信小程序中独有的&#xff0c;用来…

elasticsearch 常用语法汇总

文章目录 前言elasticsearch 常用语法汇总1. 创建索引2. 检索索引信息3. 删除索引4. 文档操作4.1. 对blog_new索引指定文档ID新增4.2. 对blog_new索引不指定文档ID新增&#xff0c;随机文档ID:4.3. 获取文档4.4. 更新文档4.5. 删除文档 5. 查询5.1. 匹配查询5.2. 范围查询5.3. …

【golang学习之旅】Go 的循环结构

系列文章 【golang学习之旅】报错&#xff1a;a declared but not used 【golang学习之旅】Go 的基本数据类型 目录 系列文章for循环基本的for循环for 变 while死循环 for-range for循环 Go 只有一种循环结构&#xff1a;for 循环 基本的for循环 和C以及Java语言一样&#xf…

社区新零售:重构邻里生活圈,赋能美好未来

新时代的邻里脉动 在城市的肌理中&#xff0c;社区作为生活的基本单元&#xff0c;正经历一场由新零售引领的深刻变革。社区新零售&#xff0c;以其独特的商业模式、创新的技术手段和以人为本的服务理念&#xff0c;重新定义了社区商业的边界&#xff0c;重构了邻里生活的形态…