前言

记录学习JavaWeb课程中的部分知识点,包括maven依赖管理、maven高阶、Mybatis、SpringBoot自动配置等。本篇是关于mybatis的相关配置,以实现对数据的增删改查功能。

MyBatis增删改查

相关配置

  1. 准备数据库表emp,sql代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
create table user(
id int unsigned primary key auto_increment comment 'ID',
name varchar(100) comment '姓名',
age tinyint unsigned comment '年龄',
gender tinyint unsigned comment '性别, 1:男, 2:女',
phone varchar(11) comment '手机号'
) comment '用户表';

insert into user(id, name, age, gender, phone) VALUES (null,'白眉鹰王',55,'1','18800000000');
insert into user(id, name, age, gender, phone) VALUES (null,'金毛狮王',45,'1','18800000001');
insert into user(id, name, age, gender, phone) VALUES (null,'青翼蝠王',38,'1','18800000002');
insert into user(id, name, age, gender, phone) VALUES (null,'紫衫龙王',42,'2','18800000003');
insert into user(id, name, age, gender, phone) VALUES (null,'光明左使',37,'1','18800000004');
insert into user(id, name, age, gender, phone) VALUES (null,'光明右使',48,'1','18800000005');


select * from user;

-- 部门管理
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());
  1. 创建一个新的springboot工程,选择引入对应的依赖,如mybatis、mysql驱动、lombok

image-20231014205542023

其实最方便的还是新建一个空的maven项目,直接把依赖配置粘贴上去(pom.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.example</groupId>
<artifactId>02-springboot-mybatis-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<java.version>8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>
  1. application.properties中引入数据库连接信息
1
2
3
4
5
6
7
8
9
10
11
12
#配置数据库的连接信息 - 四要素
#驱动类名称
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=123456

#开启mybatis日志 并输出至控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  1. 创建对应的实体类Emp(实体类属性采用驼峰命名)

构造该实体类时使用了lombok中的@Data、@NoArgsConstructor及@AllArgsConstructor,简化了无参和带有各参数的构造,避免重复使用alt + insert生成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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; // 入职日期
private Integer deptId; // 部门ID
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 修改时间
}
  1. 准备Mapper接口 EmpMapper
1
2
3
4
5
6
7
8
9
10
11
package com.itheima.mapper;

import com.itheima.pojo.Emp;
import org.apache.ibatis.annotations.*;

import java.time.LocalDate;
import java.util.List;

@Mapper
public interface EmpMapper {
}

完成后的项目结构如下:

image-20231014204435761

增加

emp表的内容如下:

image-20231014224949194

如果需要新增数据,sql语句应为:

1
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');

对应的接口方法为:

1
2
3
4
5
6
7
@Mapper
public interface EmpMapper {

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

}

参数占位符

#{…}为MyBatis的参数占位符,还有一种形式为${…}。需要注意花括号中的名称是对象的属性名(采用驼峰命名),不是数据库中的字段名。

参数占位符

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

预编译SQL

预编译SQL可以提升性能,将sql语句参数化,编译一次之后会将编译后的SQL语句缓存起来,可多次运行,不需要对相同的sql语句做重复编译。同时将敏感字进行转义,保障SQL的安全性。

主键返回

如果需要在添加数据后,返回该数据对应数据表中的主键(id),只需要添加如下注解。

1
2
//会自动将生成的主键值,赋值给emp对象的id属性
@Options(useGeneratedKeys = true,keyProperty = "id")

删除

根据主键删除数据,sql语句如下:

1
delete from emp where id = 17;

接口方法如下:

1
2
3
4
5
6
7
@Mapper
public interface EmpMapper {

@Delete("delete from emp where id = #{id}")
public void delete(Integer id);

}

修改

根据主键修改数据,与增加数据的方式相同,sql语句如下:

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

接口方法如下:

1
2
3
4
5
6
7
@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);

}

查询

根据主键查询数据,sql语句如下:

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

查询结果中的deptId、createTime、updateTime为空, 因为数据表中的字段与实体类中的属性名不一致,导致mybatis不能自动封装。

解决方案

  1. 字段起别名

  1. @Results注解

  1. 开启mybatis驼峰命名法自动映射开关

条件查询

在实际使用中,我们可能需要根据姓名、性别、入职时间及最后修改时间多项条件对员工表进行模糊查询,

  • 姓名:要求支持模糊匹配

  • 性别:要求精确匹配

  • 入职时间:要求进行范围查询

  • 根据最后修改时间进行降序排序

可能使用的sql语句示例如下:

1
2
3
4
5
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;

对应两种可以使用的接口方法:

第一种(使用${…}进行字符串拼接):

1
2
3
4
@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);

该方法并不是预编译的形式,所以效率不高、且存在sql注入风险。

第二种(使用MySQL提供的字符串拼接函数concat):

1
2
3
@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);

函数:concat(’%’ , ‘关键字’ , ‘%’),此方法生成的SQL都是预编译的SQL语句(性能高、安全)

image-20231015210307268

需要注意编写代码中的参数名规范,保证接口中方法的形参名和SQL语句中的参数占位符名相同。参数名在不同的SpringBoot版本中,处理方案也不同。

xml映射文件

通过id(对应的方法)找到对应的sql语句 来完成数据库的操作

https://mybatis.net.cn/getting-started.html