目录
[1.1 JDBC 介绍](#1.1 JDBC 介绍)
[1.2 查询数据 -- 用户登录案例](#1.2 查询数据 – 用户登录案例)
[1.3 代码剖析](#1.3 代码剖析)
[预编译 SQL](#预编译 SQL)
[1.4 SQL 注入与防范](#1.4 SQL 注入与防范)
[1.5 增删改数据](#1.5 增删改数据)
[2.1 MyBatis 介绍](#2.1 MyBatis 介绍)
[2.2 快速入门](#2.2 快速入门)
[步骤一:创建 SpringBoot 工程,引入依赖](#步骤一:创建 SpringBoot 工程,引入依赖)
[步骤四:编写 Mapper 接口](#步骤四:编写 Mapper 接口)
[2.3 辅助配置](#2.3 辅助配置)
[SQL 提示配置](#SQL 提示配置)
[MyBatis 日志输出](#MyBatis 日志输出)
[2.4 JDBC VS MyBatis](#2.4 JDBC VS MyBatis)
[2.5 数据库连接池](#2.5 数据库连接池)
[2.6 增删改查操作](#2.6 增删改查操作)
[① 删除](#① 删除)
[② 新增](#② 新增)
[③ 修改](#③ 修改)
[④ 查询](#④ 查询)
[2.7 XML 映射配置](#2.7 XML 映射配置)
[MyBatisX 插件](#MyBatisX 插件)
[三、SpringBoot 配置文件](#三、SpringBoot 配置文件)
[3.1 从 properties 到 YML](#3.1 从 properties 到 YML)
[3.2 YML 语法规则](#3.2 YML 语法规则)
[3.3 项目配置改造](#3.3 项目配置改造)
前言
在学习 MySQL 时,我们习惯使用图形化工具(如 IDEA、DataGrip)来操作数据库。但作为一名后端开发人员,最终必须通过 Java 程序来完成数据库操作。
在 Java 操作数据库的众多技术中,最底层、最基础的就是 JDBC。

JDBC(Java DataBase Connectivity) 是 Java 语言操作关系型数据库的一套 API。它虽然基础,但直接使用会比较繁琐。因此,企业开发中通常会使用基于 JDBC 封装的高级框架,目前市场份额最大的是 MyBatis ,其次是 MyBatis Plus。
一、JDBC
1.1 JDBC 介绍
JDBC 的本质 是一套由 Sun 公司定义的操作关系型数据库的规范(接口) 。各数据库厂商(如 MySQL、Oracle)去实现这些接口,并提供相应的驱动 jar 包。
我们在 Java 代码中使用 JDBC 接口编程,真正执行的是驱动包中的实现类。
有了 JDBC,就可以在 Java 代码中执行 SQL 了,比如这样一段代码:
1.2 查询数据 -- 用户登录案例
需求
基于 JDBC 实现用户登录查询,本质就是执行如下 SQL:
sql
SELECT * FROM user WHERE username = 'linchong' AND password = '123456';
准备工作
-
创建 Maven 项目
-
创建数据库
web及user表sqlCREATE TABLE user( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'ID,主键', username VARCHAR(20) COMMENT '用户名', password VARCHAR(32) COMMENT '密码', name VARCHAR(10) COMMENT '姓名', age TINYINT UNSIGNED COMMENT '年龄' ) COMMENT '用户表'; INSERT INTO user VALUES (1, 'daqiao', '123456', '大乔', 22), (2, 'xiaoqiao', '123456', '小乔', 18), (3, 'diaochan', '123456', '貂蝉', 24), (4, 'lvbu', '123456', '吕布', 28), (5, 'zhaoyun', '12345678', '赵云', 27);
代码实现
1) 引入依赖(pom.xml)
XML
<dependencies>
<!-- MySQL JDBC driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- JUnit5 单元测试 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
2) 编写测试类
java
public class JDBCTest {
@Test
public void testJdbc() throws Exception {
// 1. 获取连接
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/web", "root", "1234");
// 2. 预编译 SQL
PreparedStatement pstmt = conn.prepareStatement(
"SELECT * FROM user WHERE username = ? AND password = ?");
pstmt.setString(1, "daqiao");
pstmt.setString(2, "123456");
// 3. 执行查询
ResultSet rs = pstmt.executeQuery();
// 4. 处理结果集
while (rs.next()) {
int id = rs.getInt("id");
String uName = rs.getString("username");
String pwd = rs.getString("password");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("ID: " + id + ", Username: " + uName
+ ", Password: " + pwd + ", Name: " + name + ", Age: " + age);
}
// 5. 关闭资源
rs.close();
pstmt.close();
conn.close();
}
}
实际项目中,用户名和密码应该是动态传入的。我们可以使用 JUnit 参数化测试 来传递不同参数:
java
@ParameterizedTest
@CsvSource({"daqiao,123456"})
public void testJdbc(String _username, String _password) throws Exception {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/web", "root", "1234");
PreparedStatement pstmt = conn.prepareStatement(
"SELECT * FROM user WHERE username = ? AND password = ?");
pstmt.setString(1, _username);
pstmt.setString(2, _password);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) { /* 处理结果 */ }
// 关闭资源...
}
1.3 代码剖析
ResultSet(结果集)
ResultSet封装了查询结果,常用方法:
next():移动光标到下一行,返回布尔值(是否有数据)。
getXxx("列名"):获取当前行指定列的值(推荐用列名,而不是列索引)。
预编译 SQL
SQL 语句有静态拼接 和预编译两种写法:
| 方式 | 示例 | 特点 |
|---|---|---|
| 静态 SQL | "SELECT ... WHERE username = 'daqiao'" |
参数直接拼接,不安全 |
| 预编译 SQL | "SELECT ... WHERE username = ? AND password = ?" |
用 ? 占位,参数动态传递 |
预编译 SQL 的两大好处:
-
防止 SQL 注入
-
性能更高(模板缓存)
1.4 SQL 注入与防范
SQL 注入是指攻击者通过输入特殊的参数,改变原始 SQL 语义,从而非法访问数据。最经典的场景就是登录。
例如,攻击者在密码框输入**' or '1'='1**,拼接出的 SQL 变成:
sql
SELECT * FROM user WHERE username='任意值' AND password='' or '1'='1';
由于 '1'='1' 恒成立,or 导致条件总为真,于是能查出数据,登录成功。
解决方案 :使用预编译 SQL 。此时
' or '1'='1会被当作一个完整的字符串参数处理,SQL 语义不会被改变。
性能更高的原因
预编译的 SQL 语句模板会被数据库编译并缓存,后续执行只需传入参数,减少了编译开销。
1.5 增删改数据
需求
执行更新语句:
sql
UPDATE user SET password = '123456', gender = 2 WHERE id = 1;
代码实现
java
@ParameterizedTest
@CsvSource({"1,123456,25"})
public void testUpdate(int userId, String newPassword, int newAge) throws Exception {
// 建立数据库连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");
// SQL 更新语句
String sql = "UPDATE user SET password = ?, age = ? WHERE id = ?";
// 创建预编译的PreparedStatement对象
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setString(1, newPassword); // 第一个问号对应的参数
pstmt.setInt(2, newAge); // 第二个问号对应的参数
pstmt.setInt(3, userId); // 第三个问号对应的参数
// 执行更新
int rowsUpdated = pstmt.executeUpdate();
// 输出结果
System.out.println(rowsUpdated + " row(s) updated.");
// 关闭资源
pstmt.close();
conn.close();
}
注意区分:
DQL (查询):调用
executeQuery(),返回ResultSetDML (增删改):调用
executeUpdate(),返回int(影响行数)
二、MyBatis
2.1 MyBatis 介绍
MyBatis 是一款优秀的持久层框架 ,用于大幅度简化 JDBC 的开发。它本是 Apache 的开源项目 iBatis,后来更名为 MyBatis(官网:https://mybatis.org/mybatis-3/zh/index.html
)。
持久层:就是负责操作数据库的那一层(DAO 层)。
框架:一个半成品软件,提供可重用的代码基础,让开发更高效、规范。
使用 MyBatis,原本几十行的 JDBC 查询代码,只需简单几行:
java
@Select("select * from user")
List<User> findAll();
2.2 快速入门
目标:使用 MyBatis 查询所有用户数据。
步骤一:创建 SpringBoot 工程,引入依赖
在**pom.xml** 中会自动加入 MyBatis 起步依赖和 MySQL 驱动:
步骤二:准备数据与实体类
数据库沿用之前的 user 表。创建实体类 User:
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Integer age; //年龄
}
步骤三:配置数据源
在 **application.properties**中配置数据库连接信息:
java
#数据库访问的url地址
spring.datasource.url=jdbc:mysql://localhost:3306/web
#数据库驱动类类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#访问数据库-用户名
spring.datasource.username=root
#访问数据库-密码
spring.datasource.password=root@1234
步骤四:编写 Mapper 接口
在 com.itheima.mapper 包下创建 UserMapper 接口:
java
import com.itheima.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
/**
* 查询全部
*/
@Select("select * from user")
public List<User> findAll();
}
@Mapper:标识 MyBatis 的 Mapper,运行时会生成代理对象交给 Spring IOC 容器。
@Select:定义 select 查询语句。
步骤五:单元测试
java
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testFindAll(){
List<User> userList = userMapper.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
运行结果将打印所有用户信息。
2.3 辅助配置
SQL 提示配置
在 IntelliJ IDEA 中,为了在注解或 XML 里写 SQL 时有语法提示和表名识别,可以配置数据库连接:
MyBatis 日志输出
添加配置后,控制台可以看到执行的 SQL 语句:
java
#mybatis的配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2.4 JDBC VS MyBatis
| JDBC 的缺点 | MyBatis 的解决方案 |
|---|---|
| 数据库连接信息硬编码 | 统一配置在 application.properties 中 |
| 结果集手动解析封装 | 自动映射为实体类 |
| 频繁创建/释放连接,资源浪费 | 内置数据库连接池,复用连接 |
使用 SpringBoot + MyBatis 时,我们只需重点关注:
配置文件 :
spring.datasource.xxxMapper 接口:编写 SQL 语句
2.5 数据库连接池
什么是连接池?
-
没有连接池:每次操作都要新建连接,用完关闭,频繁创建销毁消耗性能。
-
有了连接池:应用启动时预先创建一定数量的连接放入池中,需要时借用,用完后归还,重复使用。


好处:资源重用、响应更快、避免连接遗漏。
常见产品
-
HikariCP:SpringBoot 默认连接池,性能极佳。
-
Druid:阿里巴巴开源,功能强大,监控能力强。
切换为 Druid:
1.引入依赖:
XML
<dependency>
<!-- Druid连接池依赖 -->
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
</dependency>
2.配置(.properties 或 .yml):
XML
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/web
spring.datasource.druid.username=root
spring.datasource.druid.password=1234
启动后日志中会显示使用了 DruidDataSource。

2.6 增删改查操作
① 删除
java
@Delete("delete from user where id = #{id}")
Integer deleteById(Integer id);
#{id}:预编译占位符,方法参数会替换它。返回值
Integer表示影响行数。
② 新增
java
@Insert("insert into user(username, password, name, age) values(#{username}, #{password}, #{name}, #{age})")
void insert(User user);
直接将实体对象的属性填入
#{}。
③ 修改
java
@Update("update user set username=#{username}, password=#{password}, name=#{name}, age=#{age} where id=#{id}")
void update(User user);
④ 查询
java
@Select("select * from user where username = #{username} and password = #{password}")
User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
当方法有多个简单类型参数时,建议使用
@Param指定名称。SpringBoot 项目默认保留方法形参名,如果不用
@Param,也可以直接#{参数名},但显式标注更清晰。
注意:
Mybatis的 提供的符号,有两个,一个是
#{...},另一个是${...},区别如下:|--------|-------------------------------|---------------|-------------|
| 符号 | 说明 | 场景 | 优缺点 |
| #{...} | 占位符。执行时,会将#{...}替换为?,生成预编译SQL | 参数值传递 | 安全、性能高 (推荐) |
| ${...} | 拼接符。直接将参数拼接在SQL语句中,存在SQL注入问题 | 表名、字段名动态设置时使用 | 不安全、性能低 |那在企业项目开发中, 强烈建议使用 #{...} 。
2.7 XML 映射配置
对于复杂的 SQL 语句,官方推荐使用 XML 映射文件。
规范
XML 文件与 Mapper 接口同包同名。
namespace必须为 Mapper 接口的全限定名。每个 SQL 标签的
id与接口方法名一致 ,resultType与返回类型一致。

实现示例
在 resources 下创建 com/itheima/mapper/UserMapper.xml:
XML
<?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="findAll" resultType="com.itheima.pojo.User">
select * from user
</select>
</mapper>
同时在
UserMapper接口中去掉@Select注解,只保留方法声明(不要同时存在)。
MyBatisX 插件
安装 MyBatisX 插件后,可以快速在接口和 XML 之间跳转,提升开发效率。

三、SpringBoot 配置文件
3.1 从 properties 到 YML
application.properties采用key=value格式,配置一多就显得臃肿,层次不清晰。SpringBoot 还支持 YAML 格式(
.yml/.yaml),它以数据为中心,结构更直观。
对比示例:

3.2 YML 语法规则
编辑
大小写敏感
键值对使用
key: value,冒号后必须有空格缩进表示层级关系(只能用空格,不能使用 Tab)
相同层级左侧对齐即可
#表示注释
数据格式示例:
- 对象/Map:
XML
user:
name: zhangsan
age: 18
password: 123456
- 数组/List/Set:
XML
hobby:
- java
- game
- sport
提示:如果值以
0开头,需要用单引号包起来(否则会被当成八进制),例如id: '0123'。
3.3 项目配置改造
将之前的
application.properties重命名(例如_application.properties),然后创建application.yml:
XML
#数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/web01
username: root
password: root@1234
#mybatis配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
重新运行测试,效果与之前完全一致,且配置文件更加清晰。
总结
-
JDBC 是 Java 操作数据库的底层基石,需要手动管理连接、编写大量的模板代码,容易产生 SQL 注入风险。通过预编译 SQL 可以有效防注入、提升性能。
-
MyBatis 在 JDBC 的基础上做了优雅封装:连接信息外置、结果自动映射、集成连接池,让我们只需专注编写 SQL 和 Mapper 接口。
-
SpringBoot 配置文件支持 YML 格式,简洁直观,推荐在项目中使用。

编辑