MyBatis入门学习笔记(ii)
一、这一章在讲什么
本章学习 MyBatis 框架的基础用法------如何在 Spring Boot 项目中用 MyBatis 操作 MySQL 数据库。主要讲了两种配置 SQL 的方式:注解方式 (适合简单增删改查)和 XML 映射文件方式 (适合复杂 SQL),以及 application.properties 中 MyBatis 相关的核心配置项。
二、核心概念
1. 注解方式 CRUD
MyBatis 提供了四个常用注解直接在 Mapper 接口上写 SQL:
| 注解 | 作用 | 示例 |
|---|---|---|
@Select |
查询 | @Select("select * from user where id = #{id}") |
@Insert |
新增 | @Insert("insert into user(name, age) values(#{name}, #{age})") |
@Update |
修改 | @Update("update user set name=#{name} where id=#{id}") |
@Delete |
删除 | @Delete("delete from user where id = #{id}") |
- 是什么:把 SQL 直接写在 Java 接口方法上的注解,MyBatis 会自动生成实现类执行 SQL。
- 为什么引入:避免手写 JDBC 样板代码,一行注解搞定增删改查。
- 怎么实现:MyBatis 通过 JDK 动态代理,在运行时根据注解中的 SQL 和方法的参数/返回值,自动生成 Mapper 接口的实现对象。
- 易混淆点 :注解里写的是 SQL 字符串,参数用
#{}而非 Java 的+拼接。
2. #{} 占位符 vs ${} 字符串拼接
- 是什么:两种在 SQL 中引用 Java 参数的方式。
- 区别 :
#{}:预编译占位符,SQL 变成select * from user where id = ?,参数值安全传入,防止 SQL 注入。${}:字符串拼接,直接把参数值拼进 SQL,有 SQL 注入风险。
- 原理 :
#{}底层走 JDBC 的PreparedStatement(预编译),${}走Statement(字符串拼接)。 - 易混淆点 :
#{}只能代替值的位置,不能代替表名、列名。
3. DML 语句的返回值
- 是什么 :
@Update、@Delete、@Insert方法返回int,表示影响了多少行数据。 - 作用:判断操作是否成功------返回 0 说明没删到/没改到,返回 >0 说明生效。
- 易混淆点 :返回
void也能执行成功,只是拿不到影响行数。
4. @Param 注解
- 是什么 :给 Mapper 接口方法的形参起名字,让
#{}能正确引用。 - 什么时候必须写:多个参数 + 非 SpringBoot 官方骨架项目。
- 什么时候可省略:单参数;或 SpringBoot 官方骨架项目(编译时保留参数名)。
- 建议 :多参数始终写
@Param,代码更清晰。
java
@Select("select * from user where username=#{uname} and password=#{pwd}")
User login(@Param("uname") String username, @Param("pwd") String password);
5. XML 映射文件
- 是什么 :把 SQL 写在
.xml文件里,与 Java 接口分离。 - 为什么引入:复杂 SQL(动态条件、多表关联)用 XML 更清晰。
- 三规则(缺一不可):
| 规则 | 说明 |
|---|---|
| 同包同名 | XML 和 Mapper 接口同一包路径下 |
| namespace | XML 的 namespace = Mapper 接口全限定名 |
| id 匹配 | XML 中 SQL 标签的 id = 接口方法名 |
- 易混淆点 :
resources下要逐级建文件夹(com/itheima/mapper),不是一个叫com.itheima.mapper的文件夹。
6. 注解 vs XML
| 注解 | XML | |
|---|---|---|
| 适用 | 简单增删改查 | 复杂 SQL |
| 优点 | 简洁直观 | 支持动态 SQL、清晰 |
| 缺点 | 不支持复杂逻辑 | 配置繁琐 |
两者可混合使用。
7. application.properties 核心配置
properties
# 数据源(Druid 连接池)
spring.datasource.url=jdbc:mysql://localhost:3306/web01
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=1234
# SQL 日志(调试必备)
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# XML 映射文件位置
mybatis.mapper-locations=classpath:mapper/*.xml
# 实体类别名包
mybatis.type-aliases-package=com.itheima.pojo
# 自动驼峰映射(user_name → userName)
mybatis.configuration.map-underscore-to-camel-case=true
| 配置项 | 作用 |
|---|---|
log-impl |
打印 SQL 到控制台 |
mapper-locations |
指定 XML 文件路径 |
type-aliases-package |
XML 里类名可简写 |
map-underscore-to-camel-case |
自动下划线转驼峰 |
三、重难点
#{} vs ${} --- 最重要面试题
结论 :永远优先用 #{},只有动态表名/列名等极少数场景才用 ${}。
原因 :#{} 走预编译,参数值被当作"数据"而非"SQL 的一部分",从根本上堵死 SQL 注入。${} 直接把字符串拼进 SQL,攻击者可注入恶意 SQL。
通俗比喻 :#{} 是银行柜台的防弹玻璃窗口------你递进去的是"数据",柜台里处理;${} 是把陌生人直接放进金库------他可以干任何事。
XML 映射三规则
结论 :三层对应------位置 (同包同名)、身份 (namespace)、方法(id)。
通俗比喻:送快递------地址(同包同名)= 小区,namespace = 楼号,id = 房间号。三层都对才能送到。
四、代码理解
注解方式完整示例
java
@Mapper
public interface UserMapper {
// 查询:多参数 + @Param
@Select("select * from user where username=#{username} and password=#{password}")
User findByUsernameAndPassword(@Param("username") String username,
@Param("password") String password);
// 删除:返回 Integer 判断是否成功
@Delete("delete from user where id = #{id}")
Integer deleteById(Integer id);
// 修改:传对象,自动取属性
@Update("update user set username=#{username}, password=#{password}, " +
"name=#{name}, age=#{age} where id=#{id}")
void update(User user);
}
关键点:
- 多参数用
@Param #{id}不硬编码,动态传入- 传对象时
#{}写属性名 - 增删改返回 int 判断影响行数
XML 方式完整示例
UserMapper.java:
java
@Mapper
public interface UserMapper {
List<User> findAll();
}
UserMapper.xml:
xml
<mapper namespace="com.itheima.mapper.UserMapper">
<select id="findAll" resultType="com.itheima.pojo.User">
select id, username, password, name, age from user
</select>
</mapper>
五、易错点
- SQL 写死值 ---
where id = 5→ 应改为where id = #{id} - 多参数忘了
@Param--- 非官方骨架报错 #{}里写错名 --- 传对象写属性名,传参数写@Param名- XML 文件夹路径错误 ---
resources/com.itheima.mapper→ 应为resources/com/itheima/mapper/ #{}和${}混用 --- 除了动态表名/列名,一律用#{}- 忘配
mapper-locations--- 用了 XML 但没在 properties 里指定路径
六、记忆口诀
- 注解三兄弟 :
@Select查、@Update改、@Delete删 #{}vs${}:#{}防弹玻璃(安全),${}敞开大门(危险)- XML 三规则:同名同包是地址、namespace 是楼号、id 是房间号
- 返回值 int:增删改后看"动了几行",0 行 = 没效果
@Param:一个参数不用管,多个参数起个名- 注解 vs XML:简单的用注解,复杂的用 XML------和写文档一个道理
七、应用
- 登录验证 :
@Select查用户 → null 则失败 - 后台管理:列表用 XML(分页搜索),增删改用注解
- 返回值判断:修改后检查 >0 → 成功;=0 → 用户不存在
- 日志调试 :开
log-impl,控制台看实际 SQL - 驼峰映射 :
create_time→createTime,开map-underscore-to-camel-case
八、最终总结
本章核心六个字:"注解 XML 两把刀" 。注解适合简单增删改查,XML 适合复杂 SQL------实际项目混合使用。#{} 是默认选择、安全可靠,${} 只在特殊场景用且严防注入。XML 映射靠三规则精准对应。DML 返回值判断操作是否生效。@Param 帮多参数起名,建议始终写。配置文件开日志、配 XML 路径、开驼峰映射,省去大量麻烦。