- 发布日期
MyBatis基础
- 作者
- 姓名
- 缘
- 社交账号
文章目录
MyBatis概述
MyBatis 是一款持久层框架,主要用于简化 JDBC 开发。
在典型的三层架构中:
Controller
↓
Service
↓
Mapper / DAO
↓
Database
MyBatis 主要工作在持久层,也就是 Mapper / DAO 这一层。
使用 JDBC 直接操作数据库时,需要手动完成连接获取、SQL 执行、结果集解析和资源释放。MyBatis 对这些重复工作进行了封装,开发时通常只需要定义 Mapper 接口以及对应的 SQL。
Spring Boot + MyBatis入门
准备工作
基本步骤:
- 创建 Spring Boot 工程。
- 引入 MyBatis 和 MySQL 驱动等依赖。
- 准备数据库表和实体类。
- 配置数据库连接信息。
- 定义 Mapper 接口并编写 SQL。
例如实体类:
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
}
数据库配置
使用 application.yml:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/web
username: root
password: 1234
Mapper接口
MyBatis 的持久层接口通常命名为 XxxMapper。
@Mapper
public interface UserMapper {
@Select("select * from user")
List<User> findAll();
}
@Mapper 用于告诉 Spring:这是一个 MyBatis Mapper 接口,需要为它创建代理对象并交给 Spring 容器管理。
单元测试
Spring Boot 项目中可以通过 @SpringBootTest 加载完整的 Spring Boot 环境。
@SpringBootTest
class MybatisDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void testFindAll() {
List<User> users = userMapper.findAll();
System.out.println(users);
}
}
测试类一般放在启动类所在包或其子包中,保证 Spring Boot 能够正确扫描。
JDBC与MyBatis对比
JDBC 查询数据通常需要完成:
注册驱动
↓
获取Connection
↓
创建PreparedStatement
↓
执行SQL
↓
解析ResultSet
↓
手动封装对象
↓
释放资源
而使用 MyBatis 后:
@Mapper
public interface UserMapper {
@Select("select * from user")
List<User> findAll();
}
MyBatis 帮助处理了大量重复代码,包括数据库连接管理、SQL 执行、结果集解析、对象封装和资源释放。
数据库连接池
数据库连接池本质上是一个用于管理 Connection 的容器。
应用程序
↓ 获取连接
数据库连接池
↓
Connection 1
Connection 2
Connection 3
...
应用使用完成后,不是直接销毁连接,而是将连接归还给连接池,后续请求可以继续复用。
主要优势:
- 资源复用
- 提升系统响应速度
- 减少频繁创建连接的开销
- 避免连接未释放造成的问题
Java 数据库连接池使用统一接口 DataSource。
常见连接池包括:C3P0、DBCP、Druid、Hikari,其中 Spring Boot 默认使用 Hikari。
MyBatis增删改查
删除数据
@Delete("delete from user where id = #{id}")
int deleteById(Integer id);
执行 DML 语句时,可以使用 int 作为返回值,表示受影响的记录数。
新增数据
@Insert("""
insert into user(username, password, name, age)
values(#{username}, #{password}, #{name}, #{age})
""")
void insert(User user);
当方法参数是对象时,可以直接通过对象属性名获取对应值。
修改数据
@Update("""
update user
set username = #{username},
password = #{password},
name = #{name},
age = #{age}
where id = #{id}
""")
void update(User user);
查询数据
@Select("""
select *
from user
where username = #{username}
and password = #{password}
""")
User findByUsernameAndPassword(String username, String password);
如果需要显式指定参数名称,也可以使用 @Param:
@Select("""
select *
from user
where username = #{uname}
and password = #{pwd}
""")
User findByUsernameAndPassword(
@Param("uname") String username,
@Param("pwd") String password
);
#{}与${}
| 写法 | 原理 | 常见场景 | 特点 |
|---|---|---|---|
#{...} | 使用占位符,最终生成预编译 SQL | 普通参数值 | 安全、性能较好,推荐 |
${...} | 直接进行字符串拼接 | 动态表名、动态字段名等 | 存在 SQL 注入风险 |
例如:
@Delete("delete from dept where id = #{id}")
void delete(Integer id);
实际执行时类似:
delete from dept where id = ?
而:
@Select("select * from ${tableName}")
List<User> list(String tableName);
会把字符串直接拼接进 SQL,因此必须谨慎使用。
一般参数值优先使用
#{},只有无法使用占位符的动态 SQL 位置才考虑${}。
MyBatis结果映射
如果数据库字段名和 Java 属性名完全一致,MyBatis 可以自动完成封装。
但数据库中经常使用下划线命名:
create_time
update_time
Java 中通常使用驼峰命名:
createTime
updateTime
可以开启驼峰映射:
mybatis:
configuration:
map-underscore-to-camel-case: true
之后 MyBatis 会自动按照下划线转驼峰完成映射。
SQL日志
如果希望在开发过程中查看 MyBatis 执行的 SQL,可以配置日志输出:
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置后,控制台可以看到 MyBatis 实际执行的 SQL 和参数信息。
XML映射文件
MyBatis 除了使用注解配置 SQL,还可以使用 XML 映射文件。
Mapper 接口:
@Mapper
public interface UserMapper {
List<User> findAll();
}
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>
默认规则:
- XML 文件名称与 Mapper 接口名称一致。
- XML 中的
namespace与 Mapper 接口全限定名一致。 - SQL 标签的
id与 Mapper 方法名一致。 - 返回类型与 Mapper 方法返回类型匹配。
也可以统一放到:
src/main/resources/mapper/
并配置:
mybatis:
mapper-locations: classpath:mapper/*.xml
注解还是XML
简单 SQL 使用注解比较直接:
@Select("select * from user")
List<User> findAll();
当 SQL 较复杂时,更适合使用 XML。
简单CRUD → 注解
复杂SQL / 动态SQL → XML