计划
- JDBC基础入门
- JDBC查询与增删改
- SQL注入与预编译SQL
- MyBatis快速入门
- MyBatis注解写法与XML映射
- SpringBoot配置文件与数据库连接池
笔记
1.JDBC概述
JDBC是什么
- JDBC:Java DataBase Connectivity,使用Java语言操作关系型数据库的一套API
- 本质:Sun公司定义的一套接口规范,数据库厂商提供驱动jar包实现接口
- 执行原理:Java程序调用JDBC接口,真正执行的是数据库驱动中的实现类
Java操作数据库技术
| 技术 | 说明 |
|---|---|
| JDBC | 最底层、最基础的数据库操作技术 |
| MyBatis | 基于JDBC封装的持久层框架,简化数据库开发 |
| MyBatisPlus | 在MyBatis基础上进一步增强 |
| Hibernate / SpringDataJPA | ORM思想更强的持久层框架 |
2.JDBC查询数据
查询需求
基于JDBC实现用户登录,本质是执行一条带用户名和密码条件的查询语句:
1 | select * from user where username = 'daqiao' and password = '123456'; |
准备数据表
1 | create table user( |
JDBC查询步骤
1 | Connection conn = DriverManager.getConnection( |
ResultSet结果集
- ResultSet:封装DQL查询语句返回的结果
- next():移动光标到下一行,有数据返回true,没有数据返回false
- getXxx(…):获取当前行指定列的数据,推荐使用列名获取
3.预编译SQL与SQL注入
静态SQL与预编译SQL
| 写法 | 示例 | 问题 |
|---|---|---|
| 静态SQL | username = 'daqiao' |
参数写死,灵活性差 |
| 字符串拼接SQL | 拼接用户输入 | 容易产生SQL注入 |
| 预编译SQL | username = ? |
安全、性能更高,推荐使用 |
PreparedStatement
1 | PreparedStatement pstmt = conn.prepareStatement( |
SQL注入
- SQL注入:通过控制输入内容,修改原本SQL语句含义,达到绕过校验或攻击服务器的目的
- 典型场景:登录功能中,如果使用字符串拼接SQL,输入特殊内容可能使条件恒成立
- 解决方式:使用预编译SQL,用户输入会被当成普通参数值处理,不再改变SQL结构
4.JDBC增删改数据
执行DML语句
1 | Connection conn = DriverManager.getConnection( |
executeQuery与executeUpdate
| 方法 | 执行语句 | 返回值 |
|---|---|---|
| executeQuery() | DQL查询语句 | ResultSet结果集 |
| executeUpdate() | DML增删改语句 | 影响的记录数 |
5.MyBatis概述
MyBatis是什么
- MyBatis:一款优秀的持久层框架,用于简化JDBC开发
- 持久层:数据访问层,负责操作数据库
- 框架:半成品软件,提供通用基础代码,提高开发效率
JDBC的不足
- 数据库连接信息硬编码在Java代码中
- 查询结果解析和对象封装繁琐
- 每次操作都要创建和关闭连接,资源浪费明显
MyBatis的改进
- 数据库连接信息放到SpringBoot配置文件中
- 查询结果由MyBatis自动映射为Java对象
- 底层使用数据库连接池复用连接
6.MyBatis快速入门
使用步骤
- 创建SpringBoot工程,引入
mybatis-spring-boot-starter和mysql-connector-j - 创建数据库表,并创建与表字段对应的实体类
- 在配置文件中配置数据库连接信息
- 编写Mapper接口,并在接口上添加
@Mapper - 选择注解方式或XML方式编写SQL
- 在业务代码或测试代码中注入Mapper接口,调用方法操作数据库
核心关系
| 组成 | 作用 | 复习重点 |
|---|---|---|
| 实体类 | 封装表中一行数据 | 属性名尽量与字段名一致 |
| Mapper接口 | 定义数据库操作方法 | 方法名表达清楚要执行的操作 |
| SQL语句 | 真正操作数据库 | 可写在注解中,也可写在XML中 |
| 配置文件 | 配置数据源和MyBatis行为 | 数据库连接四要素、日志输出 |
Mapper接口基本模板
1 |
|
细节:
- Mapper接口不需要自己写实现类,MyBatis运行时会生成代理对象
@Mapper的作用是让MyBatis识别该接口,并把代理对象交给Spring IOC容器管理- DML语句可以用
int作为返回值,表示影响的记录数 - 查询多条数据用
List<实体类>,查询单条数据用实体类
7.MyBatis注解写法
适用场景
注解写法适合简单SQL,例如单表的基础增删改查。优点是直观、文件少;缺点是复杂SQL写在Java注解中可读性差。
查询
1 |
|
细节:
@Select用于写查询语句- 多条件查询时,建议使用
@Param给参数命名,SQL中通过#{参数名}取值 - 查询结果字段名与实体类属性名一致时,MyBatis可以自动封装
删除
1 |
|
细节:
#{id}不是字符串拼接,而是预编译占位符- 返回值
int表示删除了几条记录
新增
1 |
|
细节:
- 参数是对象时,
#{username}表示调用对象的getUsername()取值 - 自增主键字段通常不需要手动插入
- 字段顺序要与values中的参数顺序保持一致
修改
1 |
|
细节:
- 修改语句必须注意
where条件,缺少条件会更新整张表 - 修改对象必须包含用于定位数据的主键值
8.MyBatis XML映射写法
适用场景
XML写法适合复杂SQL,例如多条件动态查询、多表查询、复杂字段映射。优点是SQL集中、可读性更好;缺点是接口和XML之间要严格对应。
XML开发规范
| 规范 | 要求 |
|---|---|
| 文件位置 | XML映射文件与Mapper接口包路径保持一致 |
| 文件名称 | XML文件名与Mapper接口名一致,如UserMapper.xml |
| namespace | 必须写Mapper接口的全限定名 |
| SQL的id | 必须与Mapper接口方法名一致 |
| resultType | 查询返回单条记录要封装成的实体类类型 |
XML基本模板
1 |
|
查询写法
1 | <select id="findAll" resultType="com.zhang.pojo.User"> |
细节:
resultType写的是单条记录封装成什么类型,不是List<User>- 如果Mapper方法返回
List<User>,XML中仍然写resultType="com.zhang.pojo.User" id必须和接口方法名一致,否则MyBatis找不到对应SQL
增删改写法
1 | <insert id="insert"> |
细节:
<insert>、<update>、<delete>标签一般不需要写resultType- DML执行后返回影响行数,Mapper接口方法可以写
int - XML和注解不要同时给同一个方法配置SQL,否则会冲突或造成理解混乱
9.注解写法与XML写法对比
| 对比点 | 注解写法 | XML写法 |
|---|---|---|
| SQL位置 | Mapper接口方法上 | resources下的Mapper.xml中 |
| 适合场景 | 简单增删改查 | 复杂SQL、动态SQL、多表查询 |
| 优点 | 写法直接,文件少 | SQL更清晰,便于维护复杂语句 |
| 缺点 | SQL复杂时可读性差 | 配置规则多,需要接口和XML对应 |
| 选择建议 | 入门和简单SQL优先使用 | 复杂业务SQL优先使用 |
10.MyBatis参数传递细节
#{...}与${...}
| 符号 | 本质 | 结果 | 使用建议 |
|---|---|---|---|
#{...} |
参数占位符 | 会替换为?,走预编译SQL |
传递普通参数时强烈推荐 |
${...} |
字符串拼接 | 直接拼接到SQL语句中 | 只有动态表名、字段名等特殊场景才考虑 |
为什么推荐#{...}
- 可以防止SQL注入
- 可以使用预编译SQL,提高性能
- 参数值会被当成普通数据处理,不会改变SQL结构
参数来源
| Mapper方法参数 | SQL中取值方式 |
|---|---|
| 单个简单参数 | #{参数名}或#{任意名}通常都能取到 |
| 多个简单参数 | 推荐使用@Param("名称")后通过#{名称}取值 |
| 对象参数 | 通过#{属性名}取对象属性值 |
11.数据库连接池
连接池作用
- 数据库连接池是一个容器,负责分配和管理数据库连接
- 程序启动时,连接池中会提前创建一定数量的Connection对象
- 执行SQL时从连接池获取连接,执行完毕后归还连接池
- 空闲过久的连接可以被自动释放,减少连接泄露风险
连接池优点
- 资源重用
- 提升系统响应速度
- 避免频繁创建和销毁连接
- 降低数据库连接遗漏风险
常见连接池
| 连接池 | 说明 |
|---|---|
| Hikari | SpringBoot默认连接池,性能好 |
| Druid | 阿里巴巴开源连接池,功能强大 |
| C3P0 | 早期常见连接池 |
| DBCP | Apache提供的连接池 |
12.SpringBoot配置文件
properties与yml
| 配置文件 | 格式 | 特点 |
|---|---|---|
| application.properties | key=value |
简单直接,配置多时层级不够清晰 |
| application.yml / application.yaml | 缩进表示层级 | 简洁清晰,以数据为中心,推荐使用 |
yml语法规则
- 大小写敏感
- 数值前必须有空格作为分隔符
- 使用缩进表示层级关系
- 缩进不能使用Tab,只能使用空格
- 相同层级左侧对齐
#表示注释- 以0开头的值建议使用引号包裹,避免被识别为八进制
数据源配置模板
1 | spring: |
MyBatis日志配置
1 | mybatis: |
开启后,控制台可以看到MyBatis执行的SQL语句、参数和结果,方便排查数据库操作问题。
13.复习时容易忽略的细节
- Mapper接口只定义方法,不写实现类,实现类由MyBatis动态代理生成
@Mapper不能忘,否则Mapper接口不会被MyBatis识别并交给Spring管理- 注解和XML是两种SQL配置方式,同一个方法不要两边都写SQL
- XML中的
namespace必须等于Mapper接口全限定名 - XML中SQL标签的
id必须等于Mapper接口的方法名 - 查询集合时,XML的
resultType仍写集合中单个元素的类型 - DML语句返回
int可以知道影响了几条记录 - 修改和删除一定要注意
where条件,避免影响整张表 - 普通参数传递优先使用
#{...},不要为了省事使用${...} - 开启MyBatis日志后,可以在控制台观察最终执行的SQL和参数
14.核心知识点总结
| 知识点 | 说明 |
|---|---|
| JDBC | Java操作关系型数据库的底层API |
| DriverManager | 获取数据库连接 |
| Connection | 数据库连接对象 |
| PreparedStatement | 预编译SQL执行对象 |
| ResultSet | 查询结果集对象 |
| executeQuery() | 执行DQL查询语句 |
| executeUpdate() | 执行DML增删改语句 |
| SQL注入 | 通过输入改变SQL语义的攻击方式 |
| MyBatis | 简化JDBC开发的持久层框架 |
| @Mapper | 声明Mapper接口,交给MyBatis和Spring管理 |
| 注解写法 | 通过@Select、@Insert、@Update、@Delete在接口方法上写SQL |
| #{…} | 参数占位符,生成预编译SQL |
| ${…} | 字符串拼接符,存在注入风险 |
| XML映射 | 将SQL写在XML中,适合复杂SQL |
| Hikari | SpringBoot默认数据库连接池 |
| application.yml | SpringBoot推荐配置文件格式 |