02-Mybatis基础操作

news2024/11/16 13:23:14

1. Mybatis基础操作

1.1 需求
需求说明:

  • 根据资料中提供的《tlias智能学习辅助系统》页面原型及需求,完成员工管理的需求开发

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过分析以上的页面原型和需求,我们确定了功能列表:

  1. 查询
    • 根据主键ID查询
    • 条件查询
  2. 新增
  3. 更新
  4. 删除
    • 根据主键ID删除
    • 根据主键ID批量删除

1.2 准备

实施前的准备工作:

  1. 准备数据库表
  2. 创建一个新的springboot工程,选择引入对应的起步依赖(mybatis、mysql驱动、lombok)
  3. application.properties中引入数据库连接信息
  4. 创建对应的实体类 Emp(实体类属性采用驼峰命名)
  5. 准备Mapper接口 EmpMapper

准备数据库表

-- 部门管理
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, 'jinyong', '123456', '金庸', 1, '1.jpg', 4, '2000-01-01', 2, now(), now()),
(2, 'zhangwuji', '123456', '张无忌', 1, '2.jpg', 2, '2015-01-01', 2, now(), now()),
(3, 'yangxiao', '123456', '杨逍', 1, '3.jpg', 2, '2008-05-01', 2, now(), now()),
(4, 'weiyixiao', '123456', '韦一笑', 1, '4.jpg', 2, '2007-01-01', 2, now(), now()),
(5, 'changyuchun', '123456', '常遇春', 1, '5.jpg', 2, '2012-12-05',2, now(), now()),
(6, 'xiaozhao', '123456', '小昭', 2, '6.jpg', 3, '2013-09-05', 1, now(), now()),
(7, 'jixiaofu', '123456', '纪晓芙', 2, '7.jpg', 1, '2005-08-01', 1,now(), now()),
(8, 'zhouzhiruo', '123456', '周芷若', 2, '8.jpg', 1, '2014-11-09', 1,now(), now()),
(9, 'dingminjun', '123456', '丁敏君', 2, '9.jpg', 1, '2011-03-11', 1,now(), now()),
(10, 'zhaomin', '123456', '赵敏', 2, '10.jpg', 1, '2013-09-05', 1,now(), now()),
(11, 'luzhangke', '123456', '鹿杖客', 1, '11.jpg', 5, '2007-02-01',3, now(), now()),
(12, 'hebiweng', '123456', '鹤笔翁', 1, '12.jpg', 5, '2008-08-18', 3,now(), now()),
(13, 'fangdongbai', '123456', '方东白', 1, '13.jpg', 5, '2012-11-01',3, now(), now()),
(14, 'zhangsanfeng', '123456', '张三丰', 1, '14.jpg', 2, '2002-08-01', 2, now(), now()),
(15, 'yulianzhou', '123456', '俞莲舟', 1, '15.jpg', 2, '2011-05-01',2, now(), now()),
(16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, now(), now()),
(17, 'chenyouliang', '123456', '陈友谅', 1, '17.jpg', NULL, '2015-03-21', NULL, now(), now());

创建一个新的springboot工程,选择引入对应的起步依赖(mybatis、mysql驱动、lombok)
在这里插入图片描述
application.properties中引入数据库连接信息

提示:可以把之前项目中已有的配置信息复制过来即可

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

创建对应的实体类Emp(实体类属性采用驼峰命名)

package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;

@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类型对应数据表中的date类型
    private Integer deptId; //部门ID
    private LocalDateTime createTime; //创建时间,LocalDateTime类型对应数据表中的datetime类型
    private LocalDateTime updateTime; //修改时间
}

准备Mapper接口:EmpMapper

/*@Mapper注解:表示当前接口为mybatis中的Mapper接口
  程序运行时会自动创建接口的实现类对象(代理对象),并交给Spring的IOC容器管理
*/
@Mapper
public interface EmpMapper {
}

完成以上操作后,项目工程结构目录如下:
在这里插入图片描述

1.3 删除

1.3.1 功能实现

页面原型:
在这里插入图片描述

当我们点击后面的"删除"按钮时,前端页面会给服务端传递一个参数,也就是该行数据的ID。
我们接收到ID后,根据ID删除数据即可。

功能:根据主键删除数据

  • SQL语句
-- 删除id=17的数据
delete from emp where id = 17;

Mybatis框架让程序员更关注于SQL语句

  • 接口方法
package com.itheima.mapper;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface EmpMapper {

	//@Delete("delete from emp where id = 17")
	//public void delete();
	//以上delete操作的SQL语句中的id值写成固定的17,就表示只能删除id=17的用户数据
	//SQL语句中的id值不能写成固定数值,需要变为动态的数值
	//解决方案:在delete方法中添加一个参数(用户id),将方法中的参数,传给SQL语句
	
	/**
	* 根据id删除数据
	* @param id 用户id
	*/
    @Delete("delete from emp where id = #{id}") //使用#{key}方式获取方法中的参数值
    // public void delete(Integer id);
    public int delete(Integer id);
}

@Delete注解:用于编写delete操作的SQL语句

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

  • 测试
    • 在单元测试类中通过@Autowired注解注入EmpMapper类型对象
package com.itheima;

import com.itheima.mapper.EmpMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired //从Spring的IOC容器中,获取类型是EmpMapper的对象并注入
    private EmpMapper empMapper;

    @Test
    public void testDelete() {
    	//调用删除方法
        int delete = empMapper.delete(17);
        System.out.println(delete);
    }
}

1.3.2 日志输入

在Mybatis当中我们可以借助日志,查看到sql语句的执行、执行传递的参数以及执行结果。具体操作
如下:

  1. 打开application.properties文件
  2. 开启mybatis的日志,并指定输出到控制台
# 指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl

开启日志之后,我们再次运行单元测试,可以看到在控制台中,输出了以下的SQL语句信息:
在这里插入图片描述

但是我们发现输出的SQL语句:delete from emp where id = ?,我们输入的参数16并没
有在后面拼接,id的值是使用?进行占位。那这种SQL语句我们称为预编译SQL。

1.3.3 预编译SQL

1.3.3.1 介绍

预编译SQL有两个优势:

  1. 性能更高
  2. 更安全(防止SQL注入)

在这里插入图片描述

性能更高:预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句
时,不会再次编译。(只是输入的参数不同)
更安全(防止SQL注入):将敏感字进行转义,保障SQL的安全性。

1.3.3.2 SQL注入

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

由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些
SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

测试1:使用资料中提供的程序,来验证SQL注入问题
在这里插入图片描述

第1步:进入到DOS
在这里插入图片描述
第2步:执行以下命令,启动程序

#启动存在SQL注入的程序
java -jar sql_Injection_demo-0.0.1-SNAPSHOT.jar

在这里插入图片描述
第3步:打开浏览器输入 http://localhost:9090/login.html

在这里插入图片描述
发现竟然能够登录成功:
在这里插入图片描述
以上操作为什么能够登录成功呢?

  • 由于没有对用户输入内容进行充分检查,而SQL又是字符串拼接方式而成,在用户输入参数时,在
    参数中添加一些SQL关键字,达到改变SQL运行结果的目的,从而完成恶意攻击。

在这里插入图片描述

这里是引用
用户在页面提交数据的时候人为的添加一些特殊字符,使得sql语句的结构发生了变化,最终可以
在没有用户名或者密码的情况下进行登录。

测试2:使用资料中提供的程序,来验证SQL注入问题
第1步:进入到DOS
第2步:执行以下命令,启动程序:

#启动解决了SQL注入的程序
java -jar sql_prepared_demo-0.0.1-SNAPSHOT.jar

第3步:打开浏览器输入 http://localhost:9090/login.html

在这里插入图片描述
发现无法登录:
在这里插入图片描述
以上操作SQL语句的执行:
在这里插入图片描述

把整个' or '1'='1作为一个完整的参数,赋值给第2个问号( ' or '1'='1进行了转义,只
当做字符串使用)

1.3.3.3 参数占位符

在Mybatis中提供的参数占位符有两种:${…} 、#{…}

  • #{…}
    • 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
    • 使用时机:参数传递,都使用#{…}
  • ${…}
    • 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
    • 使用时机:如果对表名、列表进行动态设置时使用

注意事项:在项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。

1.4 新增

功能:新增员工信息
在这里插入图片描述
1.4.1 基本新增
员工表结构:
在这里插入图片描述
SQL语句:

insert into emp(username, name, gender, image, job, entrydate,
dept_id, create_time, update_time) 
values ('songyuanqiao','宋远桥',1,'1.jpg',2,
'2012-10-09',2,'2022-10-01 10:00:00','2022-10-01 10:00:00');

接口方法:

@Mapper
public interface EmpMapper {

    @Insert("insert into emp(id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
            "values (#{id},#{username},#{password},#{name},#{gender},#{username},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);
}

说明:#{…} 里面写的名称是对象的属性名

测试类:

package com.itheima;

import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;
import java.time.LocalDateTime;

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testInsert() {
//        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 创建员工对象
        Emp emp = new Emp(null, "liyu", "123456", "李煜", (short) 2, "/image", (short) 1, 
        LocalDate.parse("2024-05-16"), 1, LocalDateTime.now(), LocalDateTime.now());
        // 调用添加方法
        empMapper.insert(emp);
    }
}

日志输出:
在这里插入图片描述

1.4.2 主键返回

概念:在数据添加成功后,需要获取插入数据库数据的主键。

如:添加套餐数据时,还需要维护套餐菜品关系表数据。
在这里插入图片描述
业务场景:在前面讲解到的苍穹外卖菜品与套餐模块的表结构,菜品与套餐是多对多的关系,一个
套餐对应多个菜品。既然是多对多的关系,是不是有一张套餐菜品中间表来维护它们之间的关系。
在这里插入图片描述
在添加套餐的时候,我们需要在界面当中来录入套餐的基本信息,还需要来录入套餐与菜品的关联
信息。这些信息录入完毕之后,我们一点保存,就需要将套餐的信息以及套餐与菜品的关联信息都
需要保存到数据库当中。其实具体的过程包括两步,首先第一步先需要将套餐的基本信息保存了,
接下来第二步再来保存套餐与菜品的关联信息。套餐与菜品的关联信息就是往中间表当中来插入数
据,来维护它们之间的关系。而中间表当中有两个外键字段,一个是菜品的ID,就是当前菜品的
ID,还有一个就是套餐的ID,而这个套餐的 ID 指的就是此次我所添加的套餐的ID,所以我们
在第一步保存完套餐的基本信息之后,就需要将套餐的主键值返回来供第二步进行使用。这个时候
就需要用到主键返回功能。

那要如何实现在插入数据之后返回所插入行的主键值呢?

  • 默认情况下,执行插入操作时,是不会主键值返回的。如果我们想要拿到主键值,需要在Mapper
    接口中的方法上添加一个Options注解,并在注解中指定属性useGeneratedKeys=true和
    keyProperty=“实体类属性名”

主键返回代码实现:

@Mapper
public interface EmpMapper {
	
	//会自动将生成的主键值,赋值给emp对象的id属性
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("insert into emp(id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
            "values (#{id},#{username},#{password},#{name},#{gender},#{username},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);
}

测试:

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testInsert() {
//        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Emp emp = new Emp(null, "litao2", "123456", "张婉", (short) 2, "/image", (short) 1, 
        LocalDate.parse("2024-05-16"), 1, LocalDateTime.now(), LocalDateTime.now());
        empMapper.insert(emp);
        System.out.println(emp.getId());
    }
}

1.5 更新

功能:修改员工信息
在这里插入图片描述

点击"编辑"按钮后,会查询所在行记录的员工信息,并把员工信息回显在修改员工的窗体上(下个知识点学习)
在修改员工的窗体上,可以修改的员工数据:用户名、员工姓名、性别、图像、职位、入职日期、归属部门
思考:在修改员工数据时,要以什么做为条件呢?
答案:员工id

SQL语句:

update emp set username = 'linghushaoxia', name = '令狐少侠', gender =1 , 
image = '1.jpg' , job = 2, entrydate = '2012-01-01', dept_id = 2,
update_time = '2022-10-01 12:12:12' where id = 18;

接口方法:

@Mapper
public interface EmpMapper {

    //更新员工
    @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);
}

测试类:

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testUpdate() {
        // 构造员工对象
        Emp emp = new Emp(23, "litao3", "123456", "李涛", (short) 2, "/image", (short) 1,
        LocalDate.parse("2024-05-16"), 1, LocalDateTime.now(), LocalDateTime.now());

        // 执行更新员工操作
        empMapper.update(emp);
    }
}

1.6 查询

1.6.1 根据ID查询

在员工管理的页面中,当我们进行更新数据时,会点击 “编辑” 按钮,然后此时会发送一个请求到服务
端,会根据Id查询该员工信息,并将员工数据回显在页面上。
在这里插入图片描述
SQL语句:

select id, username, password, name, gender, image, job, entrydate,
dept_id, create_time, update_time from emp;

接口方法:

@Mapper
public interface EmpMapper {
	@Select("select id, username, password, name, gender, image, job,
	entrydate, dept_id, create_time, update_time from emp where id=#{id}")
	public Emp getById(Integer id);
}

测试类:

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testGetById() {
        Emp emp = empMapper.getById(20);
        System.out.println(emp);
    }
}

执行结果:
在这里插入图片描述
而在测试的过程中,我们会发现有几个字段(deptId、createTime、updateTime)是没有数据值的

1.6.2 数据封装

我们看到查询返回的结果中大部分字段是有值的,但是deptId,createTime,updateTime这几个字
段是没有值的,而数据库中是有对应的字段值的,这是为什么呢?
在这里插入图片描述
原因如下:

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

解决方案:

  1. 起别名
  2. 结果映射
  3. 开启驼峰命名

起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样

@Select("select id, username, password, name, gender, image, job, entrydate, " 
			+
			"dept_id AS deptId, create_time AS createTime, update_time AS updateTime " 
			+
			"from emp " 
			+
			"where id=#{id}")
public Emp getById(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 id, username, password, name, gender, image, job,
entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);

@Results源代码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Results {
String id() default "";

Result[] value() default {}; //Result类型的数组
}

@Result源代码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Repeatable(Results.class)
public @interface Result {
boolean id() default false;//表示当前列是否为主键(true:是主键)

String column() default "";//指定表中字段名

String property() default "";//指定类中属性名

Class<?> javaType() default void.class;

JdbcType jdbcType() default JdbcType.UNDEFINED;

Class<? extends TypeHandler> typeHandler() default
UnknownTypeHandler.class;

One one() default @One;

Many many() default @Many;
}

开启驼峰命名(推荐):如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射

驼峰命名规则: abc_xyz => abcXyz

  • 表中字段名:abc_xyz
  • 类中属性名:abcXyz
# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true

要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。

1.6.3 条件查询

在员工管理的列表页面中,我们需要根据条件查询员工信息,查询条件包括:姓名、性别、入职时间。
在这里插入图片描述
通过页面原型以及需求描述我们要实现的查询:

  • 姓名:要求支持模糊匹配
  • 性别:要求精确匹配
  • 入职时间:要求进行范围查询
  • 根据最后修改时间进行降序排序

SQL语句:

select id, username, password, name, gender, image, job, entrydate,
dept_id, create_time, update_time
from emp
where name like '%张%'
	  and gender = 1
	  and entrydate between '2010-01-01' and '2020-01-01 '
order by update_time desc;

接口方法:

  • 方式一
@Mapper
public interface EmpMapper {
@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> list(String name, Short gender, LocalDate begin,
LocalDate end);
}

这里是引用
以上方式注意事项:

  1. 方法中的形参名和SQL语句中的参数占位符名保持一致
  2. 模糊查询使用${…}进行字符串拼接,这种方式呢,由于是字符串拼接,并不是预编译的 形式,所以效率不高、且存在sql注入风险。
  • 方式二(解决SQL注入风险)
    • 使用MySQL提供的字符串拼接函数:concat(‘%’ , ‘关键字’ , ‘%’)
@Mapper
public interface EmpMapper {
	@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> list(String name, Short gender, LocalDate begin, LocalDate end);
}

执行结果:生成的SQL都是预编译的SQL语句(性能高、安全)
在这里插入图片描述

1.6.4 参数名说明

在上面我们所编写的条件查询功能中,我们需要保证接口中方法的形参名和SQL语句中的参数占位符名相同。

当方法中的形参名和SQL语句中的占位符参数名不相同时,就会出现以下问题:
在这里插入图片描述

参数名在不同的SpringBoot版本中,处理方案还不同:

  • 在springBoot的2.x版本(保证参数名一致)
    在这里插入图片描述

springBoot的父工程对compiler编译插件进行了默认的参数parameters配置,使得在编译
时,会在生成的字节码文件中保留原方法形参的名称,所以#{…}里面可以直接通过形参名获取对
应的值
在这里插入图片描述

  • 在springBoot的1.x版本/单独使用mybatis(使用@Param注解来指定SQL语句中的参数名)
    在这里插入图片描述

在编译时,生成的字节码文件当中,不会保留Mapper接口中方法的形参名称,而是使用var1、
var2、…这样的形参名字,此时要获取参数值时,就要通过@Param注解来指定SQL语句中的参
数名
在这里插入图片描述

2. Mybatis的XML配置文件

Mybatis的开发有两种方式:

  1. 注解
  2. XML

2.1 XML配置文件规范

使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建
议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

  1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下 (同包同名)
  2. XML映射文件的namespace属性为Mapper接口全限定名一致
  3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

在这里插入图片描述

标签:就是用于编写select查询语句的。

  • resultType属性,指的是查询返回的单条记录所封装的类型。

2.2 XML配置文件实现

第1步:创建XML映射文件
在这里插入图片描述
第2步:编写XML映射文件

xml映射文件中的dtd约束,直接从mybatis官网复制即可

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">

</mapper>

配置:XML映射文件的namespace属性为Mapper接口全限定名
在这里插入图片描述

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

配置:XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
	<!--查询操作-->
	<select id="list" resultType="com.itheima.pojo.Emp">
 		select * from emp
 		where name like concat('%',#{name},'%')
 		and gender = #{gender}
 		and entrydate between #{begin} and #{end}
 		order by update_time desc
	</select>
</mapper>

运行测试类,执行结果:
在这里插入图片描述

2.3 MybatisX的使用

MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。
MybatisX的安装:
在这里插入图片描述
可以通过MybatisX快速定位:
在这里插入图片描述

MybatisX的使用在后续学习中会继续分享

学习了Mybatis中XML配置文件的开发方式了,大家可能会存在一个疑问:到底是使用注解方式开发还是使用XML方式开发?

官方说明: https://mybatis.net.cn/getting-started.html
在这里插入图片描述

结论:使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

2.4 小结

在这里插入图片描述

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

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

相关文章

FreeRTOS(四)FreeRTOS列表与列表项

目录 列表 列表项 迷你列表项 列表和列表项的关系 列表相关API函数 列表初始化 列表项初始化 列表项插入 列表项末尾插入 列表项删除 列表遍历 在 FreeRTOS 中&#xff0c;列表&#xff08;List&#xff09;和列表项&#xff08;ListItem&#xff09;是核心数据结构&…

如何防止订单重复

如何防止订单重复 在整个下单流程中&#xff0c;哪里重复操作影响最大&#xff1f;确认订单只是修改订单状态从未支付改为待支付而已&#xff0c;不会对我们的主要业务产生影响&#xff0c;而在支付的时候&#xff0c;主要由第三方平台&#xff0c;我们也可以不用管&#xff0c…

记一次Windows状态栏不显示问题

文章目录 &#x1fa9f;解决方案☁️单次处理☁️有效处理 &#x1fa9f;现象&#x1fa9f;尝试的操作⭐END&#x1f31f;跋&#x1f31f;交流方式 &#x1fa9f;解决方案 ☁️单次处理 重启explorer.exe 命令行操作 注意&#xff0c;使用命令行操作的时候&#xff0c;出现…

Cocos 3.8.3 实现外描边效果(逃课玩法)

本来想着用Cocos 的Shader Graph照搬Unity的思路来加外描边&#xff0c;发现不行&#xff0c;然后我就想弄两个物体不就行了吗&#xff0c;一个是放大的版本&#xff0c;再放大的版本上加一个材质&#xff0c;这个材质面剔除选择前面的面剔除就行了&#xff0c;果不其然还真行。…

字幕制作软件有哪些?整理了适合新手的5个方法,快速导出srt字幕文件!

字幕制作软件有哪些&#xff1f;平时创作视频作品时&#xff0c;大部分会用到字幕。毕竟字幕是视频中不可或缺的一部分&#xff0c;字幕文件在传达视频内容上达到了重要的作用。 常见的字幕文件有srt、ass和sub格式。市面上比较常用的是srt字幕格式&#xff0c;这种格式几乎适用…

滑动窗口 -- 限制窗口内某元素的数量/种类

目录 长度最小的数组 题解&#xff1a; 将x减到0的最小操作数 题解&#xff1a; 最大连续1的个数 题解&#xff1a; 无重复字符的最长子串&#xff08;限制数量&#xff09; 题解&#xff1a; 水果成篮&#xff08;限制种类&#xff09; 题解&#xff1a; 找到字符串中…

Skywalking告警配置

背景 skywalking 9.7.0&#xff0c;地址&#xff1a;Backend setup | Apache SkyWalking helm&#xff1a;skywalking-helm:4.5.0&#xff0c;地址&#xff1a;skywalking-helm/chart/skywalking/values.yaml at v4.5.0 首先来说一下为什么使用skywalking告警&#xff1f; …

[半导体检测-6]:为什么晶圆缺陷检测精度越高,所需要的光源的波长越短?

目录 前言&#xff1a; 1. 光束的聚焦能力 1.1 概述 1.2 光束的聚焦能力用什么指标来标识&#xff1f; 1. 光束质量因子&#xff08;M因子&#xff09; 2. 衍射极限倍数&#xff08;β因子&#xff09; 3. 斯特列尔比&#xff08;Strehl Ratio&#xff09; 4. 远场发散…

Spring6梳理13——依赖注入之引入集合Bean属性

以上笔记来源&#xff1a; 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09;https://www.bilibili.com/video/BV1kR4y1b7Qc 13 依赖注入之引入集合Bean属性 13.1 创建Lesson类&#xff0c;student类和teacher实体类…

【LeetCode:2535. 数组元素和与数字和的绝对差 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

jmeter性能测试---csv数据文件设置

&#xff08;1&#xff09;什么时候使用CSV数据文件设置&#xff1f; 当不同的用户&#xff0c;或者同一用户多次循环时&#xff0c;都可以获取到不同的值 &#xff08;2&#xff09;使用CSV数据文件设置进行参数化的步骤&#xff1f; 实例&#xff1a; 请求&#xff1a;htt…

基于Node.js+Express+MySQL+VUE实现的计算机毕业设计共享单车管理网站

单车信息选择骑行 骑行状态留言公告/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序 功能如下&#xff1a; 一、开发目标 在共享经济日益盛行的今天&#xff0c;共享单车作为一种绿色、便捷的出行方式&#xff0c;已经深入人们的日常生活。然而&#xff0c;随着共享…

短效IP是网络世界的神秘助力者

伙伴们&#xff0c;我们都知道网络世界神秘莫测&#xff0c;在当今这个高度数字化的时代&#xff0c;网络如同一张无形的大网&#xff0c;将人们的生活和工作紧密相连&#xff0c;成为不可或缺的一部分。而在这庞大的网络背后&#xff0c;有着很多挑战和危险&#xff0c;为了能…

ps快速更换电商图片背景,轻松变成白底图

前言 在电商领域&#xff0c;一张高质量的商品图片往往能吸引更多消费者的目光&#xff0c;提升商品的点击率和转化率。而白底图&#xff0c;以其简洁、清晰、专业的特点&#xff0c;成为电商平台上商品展示的首选。然而&#xff0c;传统的手动抠图方式不仅耗时耗力&#xff0…

Linux中部署Docker环境;Docker常用操作

一&#xff0c;部署Docker环境 官网手册&#xff1a;CentOS | Docker Docs 1.1、查看一下Linux内核版本 uname -r 要求3.10版本及以上。 2.2、卸载老版本docker&#xff0c;避免产生影响 如果服务器安装过docker&#xff0c;没有卸载再次安装会导致安装失败&#xff0c;首…

Latex和Vscode安装和配置

一、Latex安装教程 打开清华大学开源软件镜像站&#xff0c;下载texlive.iso文件 右键点击ios文件&#xff0c;点击装载 配置latex安装 4. 安装过程 二、VScode安装和配置教程 打开Vscode官网&#xff0c;下载安装包 2.右键&#xff0c;以管理员身份运行VSCode安装包&#…

Day.js时间插件的安装引用与常用方法大全

&#x1f680; 个人简介&#xff1a;某大型国企资深软件研发工程师&#xff0c;信息系统项目管理师、CSDN优质创作者、阿里云专家博主&#xff0c;华为云云享专家&#xff0c;分享前端后端相关技术与工作常见问题~ &#x1f49f; 作 者&#xff1a;码喽的自我修养&#x1f9…

C++ 数据类型分类

在C中&#xff0c;数据类型可以大致分为内置类型&#xff08;Built-in Types&#xff09;、标准库类型&#xff08;Standard Library Types&#xff09;和自定义类型&#xff08;User-Defined Types&#xff09;三大类。 内置类型&#xff08;Built-in Types&#xff09; 内置…

Kafka和RabbitMQ比较

Kafka和RabbitMQ都是流行的消息队列系统&#xff0c;它们在分布式系统中扮演着至关重要的角色&#xff0c;用于异步消息传递和解耦应用组件。尽管它们共享一些基本的概念&#xff0c;但它们在设计目标、性能特性、使用场景等方面有着显著的差异。 设计目标 Kafka&#xff1a;Ka…

理解Java引用数据类型(数组、String)传参机制的一个例子

目录 理解Java引用数据类型&#xff08;数组、String&#xff09;传参机制的一个例子理解样例代码输出 参考资料 理解Java引用数据类型&#xff08;数组、String&#xff09;传参机制的一个例子 理解 引用数据类型传递的是地址。用引用类型A给引用类型B赋值&#xff0c;相当于…