Mybatis 知识总结2(基于注解的增删改查操作)

news2024/11/24 6:32:21

3.3 MyBatis 增删改查(注解方式)

  MyBatis 的增删改查是最基础最核心的功能,需要重点掌握。

需求说明

  对员工信息进行增删改查操作。

  • 查询(查询结果分页展示后续实现)
    • 根据主键ID查询
    • 根据条件查询
  • 新增
  • 更新
  • 删除
    • 根据主键 ID 删除
    • 根据主键 ID 批量删除

准备工作

  • 准备数据库表 dept 部门表emp 员工表并插入数据
-- 部门表
create table dept(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(10) not null unique comment '部门名称',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '修改时间'
) comment '部门表';
-- 插入部门表数据
insert into dept (id,name,create_time,update_time) values 
		(1,'学工部',now(),now()),
		(2,'教研部',now(),now()),
		(3,'咨询部',now(),now()),
		(4,'就业部',now(),now()),
		(5,'人事部',now(),now());
-- 员工表
create table emp(
    id int unsigned primary key auto_increment comment 'ID',
    username varchar(20) not null unique comment '用户名',
    password varchar(32) default '123456' comment '密码',
    name varchar(10) not null comment '姓名',
    gender tinyint unsigned not null comment '性别,说明:1 男,2 女',
    image varchar(300) comment '图像',
    job tinyint unsigned comment '职位,说明:1 班主任,2 讲师,3 学工主管,4 教研主管,5 咨询师',
    entrydate date comment '入职时间',
    dept_id int unsigned comment '部门ID',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '修改时间'
) comment '员工表';
-- 插入员工表数据
insert into emp (id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time) values 
		(1,'zhansan','123456','张三',1,'1.jpg',4,'2000-01-01',2,now(),now()),
		(2,'lisi','123456','李四',1,'2.jpg',2,'2015-01-01',2,now(),now()),
		(3,'wangwu','123456','王五',1,'3.jpg',4,'2008-01-01',2,now(),now()),
		(4,'wangmazi','123456','王麻子',1,'4.jpg',1,'2000-01-01',2,now(),now()),
		(5,'xiaohong','123456','小红',2,'5.jpg',5,'2009-01-01',3,now(),now());		
  • 创建一个新的 springboot 工程,选择引入对应的起步依赖(mybatis、mysql驱动、lombok)
1 2 3
  • Application.properties 配置文件中引入数据库连接信息 src/main/resources/application.properties
# 1 驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 2 数据库连接的 url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
# 3 连接数据库的用户名
spring.datasource.username=root
# 4 链接数据库的密码
spring.datasource.password=xxxx
  • 创建对应的实体类 Emp(实体类属性采用驼峰命名)src/main/java/com/ganming/pojp/Emp.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;             // ID
    private String username;        // 用户名
    private String password;        // 密码
    private String name;            // 姓名
    private Short gender;           // 性别,说明:1 男,2 女
    private String image;           // 图像url
    private Short job;              // 职位,说明:1 班主任,2 讲师,3 学工主管,4 教研主管,5 咨询师
    private LocalDate entrydate;    // 入职日期 LocalDate:封装 年月日
    private Integer deptId;         // 部门ID
    private LocalDateTime createTime;   // 创建时间 LocalDateTime:封装 元月日时分秒
    private LocalDateTime updateTime;   // 修改时间
}
  • 准备 Mapper 接口 EmpMapper src/main/java/com/ganming/mapper/EmpMapper.java
package com.ganming.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper	 // 在运行时,框架会自动的生成该接口的实现类对象(代理对象),并且将该对象交给 IOC 容器管理
public interface EmpMapper {
}

MyBatis 删除

  • 根据 ID 删除单条数据

  src/main/java/com/ganming/mapper/EmpMapper.java

// 根据 ID 删除数据
@Delete("delete from emp where id = #{id}") // 动态获取方法参数id
public void delete(Integer id);

注意事项:

  如果 mapper 接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写,如:#{id}、#{value}。

  该方法如果返回值,则为该 sql 语句执行后影响的行数。

  测试根据 ID 删除数据方法:
src/test/java/com/ganming/MybatisCrudApplicationTests.java

@Resource		// 完成依赖注入
private EmpMapper empMapper;
@Test
public void testDelete(){
    empMapper.delete(5);		// 调用 EmpMapper 中的删除方法
}
  • MyBatis 配置开启日志输出

  可以在 src/main/resources/application.properties 中,打开 mybatis 的日志,并指定输出到控制台。开启后能在控制台输出预编译 SQL。

# 指定 mybatis 输出日志的位置,输出控制台
mybatis.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
mybatis日志输出

  预编译 SQL :①性能更高;②更安全(防止 SQL 注入)

性能更高

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

MyBatis 参数占位符:

  #{…}:①执行 SQL 时,会将 #{…} 替换为 ?,生成预编译 SQL,会自动设置参数值。②使用时机:参数传递都使用 #{…};

  ${…}:①拼接 SQL 。直接将参数拼接在 SQL 语句中,存在 SQL 注入问题。②使用时机:如果对表名、列表名进行动态设置时使用;

#{...} ${...}

MyBatis插入

  src/main/java/com/ganming/mapper/EmpMapper.java

// 插入数据
    @Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            "value (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime});")
    public void insert(Emp emp);	// 用一个实体类来封装多个参数
性能更高

  src/test/java/com/ganming/MybatisCrudApplicationTests.java

@Test
public void testInsert(){
    Emp emp = new Emp();
    emp.setUsername("zhouzhiruo");
    emp.setName("周芷若");
    emp.setImage("z.jpg");
    emp.setGender((short)2);
    emp.setJob((short)1);
    emp.setEntrydate(LocalDate.of(2002,2,23));
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    emp.setDeptId(1);
    empMapper.insert(emp);
}
  • 新增(主键返回)

  如上,我们新增一个 emp 员工数据时,主键 id 是自增产生的,我们并没有传值,但是当程序中需要这个主键时(需要往其他表插入相关信息),我们该如何获取呢?

  如果直接获取 emp 的 id,将得到的是 null,如下:默认情况下,主键值是不返回的。

性能更高 性能更高

  如需返回,可在该方法上添加 @Options 注解

  useGeneratedKeys = true :表示我们需要拿到生成的主键值。

  keyProperty = "id" : 表示我们所获取到的主键赋值给 emp 对象的 id 属性上。

性能更高

MyBatis更新

  更新一般要根据一条数据的唯一键来更新其他字段,所以更新方法需要传递更新哪条数据的哪些字段值。

  src/main/java/com/ganming/mapper/EmpMapper.java

// 修改数据
@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);

  src/test/java/com/ganming/MybatisCrudApplicationTests.java

@Test
public void testUpdate(){
    Emp emp = new Emp();
    emp.setId(1);			// 跟新第一条数据
    emp.setUsername("zhaoming");
    emp.setName("赵敏");
    emp.setImage("z.jpg");
    emp.setGender((short)2);
    emp.setJob((short)1);
    emp.setEntrydate(LocalDate.of(2002,2,23));
    //emp.setCreateTime(LocalDateTime.now());	// 创建时间不需要更新了
    emp.setUpdateTime(LocalDateTime.now());		// 每次更新都需要修改更新时间
    emp.setDeptId(1);
    empMapper.update(emp);
}

MyBatis查询

  查询是有查询结果的,必须要有返回值,需要封装到实体类中,如果查出来是一条,就直接返回对应的实体类,如果查询结果是多条,就封装到实体类的集合或数组中。

  • 根据 id 查询:根据 id 在本例中只能查到一条数据,所以设置返回结果为 Emp 类型即可。

  src/main/java/com/ganming/mapper/EmpMapper.java

// 根据id查询
@Select("select * from emp where id = #{id}")
public Emp selectById(Integer id);

  src/test/java/com/ganming/MybatisCrudApplicationTests.java

// 测试查询
@Test
public void testSelectById(){
    Emp emp = empMapper.selectById(1);
    System.out.println(emp);
}

  打印的查询结果如下,可发现除了deptId、createTime、updateTime 这三个属性为 null 外,其他属性都正常显示。这是因为数据表中的字段名与需要封装的实体类 Emp 的属性名这三个没有完全对应上,数据表的命名规则常采用 a_column,而实体类的属性命名规则为aColumn。

查询结果 查询结果

  MyBatis 的数据封装:实体类属性名和数据库表查询返回的字段名一致,mybatis 会自动封装;如果不一致则不会自动封装。

  • 解决方案一(了解):给数据库表查询返回的字段名取别名,让别名和实体类属性名一致即可(需要起别名就不能用 * 来输出所有字段了)
查询结果
  • 解决方案二(了解):通过 @Results@Result 注解手动映射封装
通过 @Results, @Result 注解手动映射封装

  @Results 注解传入的参数是一个 @Result 数组;

  @Result 注解传入的参数是 column(数据库表的字段)和 property(实体类的属性名),表示把column 的值映射到 property 的值上。

  • 解决方案三(推荐):开启 mybatis 的驼峰命名自动映射开关

  开关打开则下划线分割(a_column)的数据库表字段命名会自动封装到实体类中的驼峰(aColumn)命名属性当中。

  在 src/main/resources/application.properties 中开启这项配置

开启 mybatis 的驼峰命名自动映射开关
  • 按条件查询:

  根据输入的员工姓名支持模糊匹配)、性别精确查询)、入职时间范围查询)搜索满足条件的员工信息;并对查询结果根据入职时间倒序排序

按条件查询

  src/main/java/com/ganming/mapper/EmpMapper.java

// 根据条件查询
@Select("select * from emp where name like '%${name}%' and gender = #{gender} and " +
        "entrydate between #{begin} and #{end} order by entrydate desc;")
public List<Emp> list(String name,short gender,LocalDate begin,LocalDate end);

  由于 like 模糊匹配,我们需要在关键字前后拼接上 % ,所以 like 后面一定是个字符串,字符串当中是不能使用 #{} 的,所以在这里使用 ${} 进行字符串的拼接。但是这样拼接存在性能低不安全存在 SQL 注入问题。

按条件查询

  mysql 给我们提供了一个 concat 字符串拼接函数,它可以接受多个字符串参数,将它们拼接位一个字符串:

mysql的concat函数

  利用 concat 字符串拼接比 ${} 拼接更好,排除了上述问题的隐患。

按条件查询 按条件查询

  参数名说明(了解链接:视频13:50开始)

参数名说明

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

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

相关文章

海思芯片(hi3536av100)启动模式选择

1、支持多种模式可配置 (1)支持BootRom启动 (2)支持从 SPI NOR Flash 启动 (3)支持从 SPI NAND Flash 启动 (4)支持从 eMMC 启动 (5)支持 PCIe 从片启动 2、启动方式的选择 BOOT_SEL[1:0]SFC_EMMC_BOOT_MODEMODE000SPI Nor Flash 3 Byte001SPI Nor Flash 4 Byte010SPI Nand Fl…

2005-2020全国及各省家庭承包耕地流转总面积及经营耕地面积

2005-2020全国及各省家庭承包耕地流转总面积及经营耕地面积 1、时间&#xff1a;时间&#xff1a;2005-2020年 2、范围&#xff1a;包括全国及30个省份不包括西藏 3、指标包括&#xff1a;家庭承包耕地流转总面积(亩)、家庭承包经营耕地面积(亩) 4、来源&#xff1a;农村经…

荔枝派Zero(全志V3S) tftp下载 kernel 和 nfs 挂载文件系统

文章目录 前言一、U-Boot 适配 Ethernet1、配置 U-Boot2、修改 dts 文件3、编译4、烧写到 SD 卡5、测试<1>、查看启动打印信息<2>、ping 测试 二、Kernel 适配 Ethernet1、配置 kernel2、修改 dts 文件3、编译4、拷贝到 SD 卡5、测试<1>、启动网络接口&#…

【嵌入式环境下linux内核及驱动学习笔记-(7-内核 I/O)-多路复用】

目录 2、多路复用2.1 函数select相关2.1.1 应用层select()2.1.2 FD_ZERO2.1.3 FD_SET2.1.4 FD_ISSET 2.2 函数poll相关2.2.1 poll函数 2.3 驱动层 函数2.4 实例 接上篇&#xff0c;继续内核 I/O的五种模式的解读。 2、多路复用 select&#xff0c;poll&#xff0c;epoll都是IO…

常见的接口优化技巧思路

一、背景 针对老项目&#xff0c;去年做了许多降本增效的事情&#xff0c;其中发现最多的就是接口耗时过长的问题&#xff0c;就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案。 二、接口优化方案总结 1.批处理 批量思想&#xff1a;批量操作数据…

windows如何确认服务器上程序端口是否正常

方式1&#xff1a;ping命令 ping命令说明 ping命令是个使用频率极高的网络诊断工具&#xff0c;在Windows、Unix和Linux系统下均适用。它是TCP/IP协议的一部分&#xff0c;用于确定本地主机是否能与另一台主机交换数据报。根据返回的信息&#xff0c;我们可以推断TCP/IP参数设…

类和对象 -上(C++)

目录 认识面向过程和面向对象 类的引入 类的定义 语法&#xff1a; 类的两种定义方式&#xff1a; 成员变量命名规则建议 类的访问限定符及封装 访问限定符 C 中 class 和 struct 的区别&#xff1f; 封装 类的作用域 类的实例化 类对象模型 如何计算类对象的大小 结构体的内存…

想保护你的网站?用Python来生成验证码图片

前言 随着互联网的发展&#xff0c;我们越来越多地依赖于网站和应用程序&#xff0c;而这些网站和应用程序也面临着各种各样的安全威胁&#xff0c;其中之一就是用户可能会通过脚本攻击你的网站。为了缓解这些安全风险&#xff0c;一个常见的做法是在用户进行操作时&#xff0…

关于电信设备进网许可制度若干改革举措的通告

Q&#xff1a;3月1日后&#xff0c;不再实行进网许可管理的11种电信设备是否还需要继续申请和使用标志&#xff1f; A&#xff1a;3月1日起&#xff0c;对不再实行进网许可管理的11种电信设备停止核发进网许可标志&#xff0c;已申请的标志可在证书有效期内继续使用。 Q&#…

应用启动时aerospike客户端查询rt高原因

在应用刚起步时&#xff0c;发到预发测试或者生产小部分流量进来时&#xff0c;发现aerospike的rt特别高&#xff0c;在流量稍微大点时&#xff0c;rt恢复正常。基本可以断定客户端存在预热问题。 应用没有设置连接池配置&#xff0c;因此check下默认配置 可以看到&#xff0…

c++类 笔记(陆续更新该文档)

派生类 #include <iostream> using namespace std; class Box{private://类私有&#xff0c;只有成员可以调用 也就是说你不可以通过box1.a来调用 ,这些变量其实你默认不用写private 这个变量&#xff0c;只要放在最上面他默认就是 私有int a1;protected://protected&am…

AlgoC++:课程总结

目录 课程总结前言1. 未讲解内容2. 复习2.1 矩阵求导2.2 优化方法2.3 具体的算法 3. 未来怎么学C(必看&#xff01;&#xff01;&#xff01;) 课程总结 前言 手写AI推出的全新面向AI算法的C课程 Algo C&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课…

【嵌入式环境下linux内核及驱动学习笔记-(8-内核 I/O)-信号驱动】

目录 3 信号驱动的异步通知3.1 linux异步通知编程3.1.1 什么是信号3.1.2 信号的工作流程: 3.2. 应用层3.2.1 信号接收 signal函数3.2.2 应用层 fcntl 函数3.2.3 应用层信号驱动机制步骤 3.3 驱动层3.3.1 驱动层模板3.3.2 驱动层 实现fasync函数3.3.3 fasync_helper3.3.4 struct…

Golang-常见数据结构Slice

Slice slice 翻译成中文就是切片&#xff0c;它和数组&#xff08;array&#xff09;很类似&#xff0c;可以用下标的方式进行访问&#xff0c;如果越界&#xff0c;就会产生 panic。但是它比数组更灵活&#xff0c;可以自动地进行扩容。 了解 slice 的本质, 最简单的方法就是…

MySQL 一条SQL语句是如何执行的?

总览 ​ 所以今天我们把MySQL拆解一下&#xff0c;看看里边有哪些零件。下边是MySQL的基本架构示意图。 大体来说&#xff0c;MySQL分为Server层和存储引擎两部分。 Server 层包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&am…

小白也能懂的可转债配债价格计算

可转债配债如何计算 先给理论公式&#xff1a; 配债10张/1手所需的钱数 配债所需股数 * 当前的股价 这个公式应该很好理解&#xff0c;不需要做过多的解释。 那&#xff0c; 为什么如此简单的公式&#xff0c;还是很多人不会算&#xff0c;是因为&#xff1a; 配债所需的股数跟…

类与对象之构造函数

文章目录 导读类的6个默认构造函数构造函数概念特性 析构函数概念特性 拷贝构造函数概念特性 赋值运算符重载运算符重载赋值运算符重载前置和后置重载 导读 本文是md导入的可能格式有点乱&#xff0c;希望各位理解一下 类的6个默认构造函数 默认成员函数&#xff1a;用户没有…

五一堵车 | AI“高速”车辆检测轻而易举监测大家安全

点击蓝字关注我们 关注并星标 从此不迷路 计算机视觉研究院 学习群&#xff5c;扫码在主页获取加入方式 计算机视觉研究院专栏 作者&#xff1a;Edison_G 五一节不管是离开小城镇还是进入大城市&#xff0c;每个高速路口都是堵车&#xff0c;现在人工智能愈来愈发达&#xff0c…

git fetch时,FETCH_HEAD和.git\refs\remotes\origin会有哪些变化

目录 github远程仓库状态clone 到本地对新clone的仓库直接 fetchgit fetchgit fetch origingit fetch origin test1git fetch origin test2:test22 结论 github远程仓库状态 clone 到本地 git fetchgit fetch origingit fetch origin test3git fetch origin test2:test22 git f…

Photon AI Translator 和做产品的一些思考

近 4 个月内我一直在做 Apple 平台的产品&#xff0c;虽然从使用量来说「简体中文」用户是占多数&#xff0c;但我一直有做多语言的支持&#xff1a;英语、简体中文和繁体中文。习惯上 Google 翻译的我&#xff0c;基本上在使用 Xcode 过程中也会一直在浏览器开着 Google Trans…