目录
一、为什么需要 MyBatis?
1. JDBC 的痛点
JDBC 操作数据库需要手动管理连接、编写重复代码(如创建连接、释放资源)、处理异常等。例如,插入一条数据的代码需要:
-
创建
Connection
和PreparedStatement
-
绑定参数
-
执行 SQL
-
处理结果
-
关闭资源
生活例子:就像每次做饭都要手动点火、洗菜、切菜、炒菜,最后还要刷锅。而 MyBatis 则像一台智能炒菜机,你只需要告诉它菜谱(SQL),剩下的步骤自动完成。
2. MyBatis 的优势
-
简化开发:通过配置和映射,自动处理资源管理和结果集封装。
-
灵活性:支持注解和 XML 两种方式编写 SQL。
-
性能优化:内置数据库连接池(如 Hikari),避免频繁创建/销毁连接。
3.如何使用
二、MyBatis 核心概念
1. 持久层与分层架构
类比:
餐厅点餐流程:顾客(Controller)下单 → 厨师(Service)处理 → 服务员(Dao)从厨房(数据库)取菜。
-
作用:简化数据库操作,将 SQL 与 Java 代码解耦。
-
持久层:负责与数据库交互(DAO 层)。
-
分层架构:Controller(接收请求) → Service(业务逻辑) → Dao(数据库操作)。
2. 两种开发方式
(1)注解方式
直接在接口方法上使用 @Select
、@Insert
等注解编写 SQL:
@Select("SELECT * FROM userinfo WHERE id = #{id}")
UserInfo queryById(Integer id);
(2)XML 方式
将 SQL 写在 XML 文件中,与接口方法绑定:
<!-- UserInfoMapper.xml -->
<select id="queryAllUser" resultType="UserInfo">
SELECT * FROM userinfo
</select>
对比:
-
注解:适合简单 SQL,代码简洁。
-
XML:适合复杂 SQL(如动态 SQL),便于维护。
3. MyBatis 核心配置
3.1 数据库连接配置
在 application.yml
或 application.properties
中配置数据库信息:
//localhost是本地数据库名称
//mybatis_test代表需要本地数据库名称内的子文件
//username和password是你电脑上的数据库账号和密码
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_test?useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
3.2 日志配置(查看 SQL 执行细节)
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
效果:控制台会打印执行的 SQL 语句和参数,方便调试。
三、基础操作:增删改查
1. 查询(Select)
1.1 注解方式
代码示例:
@Mapper
public interface UserMapper {
@Select("SELECT * FROM userinfo WHERE id = #{id}")
UserInfo getUserById(Integer id);
}
结果映射问题
-
字段名与属性名不一致(如
create_time
vscreateTime
):-
解决方案:
-
起别名:
SELECT create_time AS createTime
-
-
开启驼峰命名(推荐):
-
-
结果映射
-
-
-
mybatis:
configuration:
map-underscore-to-camel-case: true
1.2 XML 方式
步骤:
1.创建 XML 文件 UserMapper.xml
:
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" resultType="com.example.model.UserInfo">
SELECT * FROM userinfo WHERE id = #{id}
</select>
</mapper>
2.配置XML路径
mybatis:
mapper-locations: classpath:mapper/*.xml
常见问题
2. 插入(Insert)
返回自增主键
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO userinfo (username, password) VALUES (#{username}, #{password})")
Integer insert(UserInfo userInfo);
-
作用:插入后自动将数据库生成的主键赋值给
userInfo.id
。
3. 删除(Delete)
@Delete("DELETE FROM userinfo WHERE id = #{id}")
void delete(Integer id);
4.更新(Update)
@Update("UPDATE userinfo SET username = #{username} WHERE id = #{id}")
void update(UserInfo userInfo);
四、参数传递与 SQL 注入
1. #{}
vs ${}
特性 | #{} (预编译) | ${} (字符串替换) |
---|---|---|
安全性 | 防 SQL 注入 | 有注入风险 |
引号处理 | 自动添加引号(如字符串) | 直接替换,需手动加引号 |
适用场景 | 值参数(如 WHERE 条件) | 动态表名、排序字段 |
示例:
// 安全查询(防注入)
@Select("SELECT * FROM userinfo WHERE username = #{name}")
UserInfo queryByName(String name);
// 动态排序(必须用 ${})
@Select("SELECT * FROM userinfo ORDER BY ${sortField}")
List<UserInfo> queryAllUserBySort(String sortField);
//$存在注入风险的代码示例
@Select("SELECT * FROM userinfo ORDER BY ${sortField}")
List<UserInfo> queryAllUserBySort(String sortField);
//若攻击者传入恶意参数 sortField = "1; DROP TABLE userinfo;--",拼接后的 SQL 变为:
SELECT * FROM userinfo ORDER BY 1; DROP TABLE userinfo;--
//数据库会执行 DROP TABLE userinfo,导致表被删除。
五、日志配置
1. 配置 MyBatis 日志
在 application.yml
中:
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
效果:控制台打印执行的 SQL、参数和结果。
六、数据库连接池
1. 作用
-
复用连接:避免频繁创建和销毁连接,提升性能。
-
常见实现:
-
HikariCP:SpringBoot 默认,轻量高效。
-
Druid:功能强大,支持监控。
-
2. 配置 Druid
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
七、企业开发规范
-
表名与字段名:使用小写和下划线(如
user_info
)。 -
必备字段:
id
(主键)、create_time
、update_time
。 -
避免
SELECT *
:明确指定查询字段,减少网络开销。
八、总结
1. MyBatis 核心价值
-
简化 JDBC:通过配置和映射,减少模板代码。
-
灵活 SQL:支持注解和 XML 两种方式。
-
安全高效:预编译防注入,连接池提升性能。
2. 学习路径
-
配置数据源和日志。
-
编写注解/XM L映射。
-
实现增删改查。
-
处理结果映射和参数传递。