目录
1. MyBatis简介
1.1 什么是MyBatis?
MyBatis是一个优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
核心特点:
- 简单易学:本身就很小且简单
- 灵活:不会对应用程序或者数据库的现有设计强加任何影响
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离
- 支持动态SQL:根据不同条件拼接SQL语句
1.2 MyBatis架构
应用程序
↓
SqlSession (会话)
↓
Executor (执行器)
↓
StatementHandler (语句处理器)
↓
ParameterHandler (参数处理器) → ResultSetHandler (结果处理器)
↓
JDBC
↓
数据库
1.3 MyBatis与其他持久层框架对比
特性 | MyBatis | Hibernate | JPA |
---|---|---|---|
学习难度 | 简单 | 复杂 | 中等 |
SQL控制 | 完全控制 | 部分控制 | 部分控制 |
性能优化 | 容易 | 复杂 | 中等 |
开发效率 | 中等 | 高 | 高 |
2. 环境搭建与配置
2.1 Maven依赖配置
<!-- pom.xml -->
<dependencies>
<!-- MyBatis核心依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- 数据库驱动,以MySQL为例 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 日志依赖(可选) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
2.2 项目结构
src/main/java/
├── com/example/
│ ├── entity/ # 实体类
│ ├── mapper/ # Mapper接口
│ ├── service/ # 业务层
│ └── utils/ # 工具类
src/main/resources/
├── mybatis-config.xml # MyBatis主配置文件
├── mapper/ # SQL映射文件
└── log4j.properties # 日志配置
3. 核心配置文件详解
3.1 mybatis-config.xml主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性配置 -->
<properties resource="database.properties"/>
<!-- 设置 -->
<settings>
<!-- 开启驼峰命名转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置超时时间 -->
<setting name="defaultStatementTimeout" value="30"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 类型别名 -->
<typeAliases>
<!-- 单个别名 -->
<typeAlias type="com.example.entity.User" alias="User"/>
<!-- 包扫描 -->
<package name="com.example.entity"/>
</typeAliases>
<!-- 类型处理器 -->
<typeHandlers>
<typeHandler handler="com.example.handler.MyTypeHandler"/>
</typeHandlers>
<!-- 环境配置 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<!-- 使用相对于类路径的资源引用 -->
<mapper resource="mapper/UserMapper.xml"/>
<!-- 使用完全限定资源定位符(URL) -->
<!-- <mapper url="file:///var/mappers/UserMapper.xml"/> -->
<!-- 使用映射器接口实现类的完全限定类名 -->
<!-- <mapper class="com.example.mapper.UserMapper"/> -->
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<!-- <package name="com.example.mapper"/> -->
</mappers>
</configuration>
3.2 database.properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456
3.3 重要设置详解
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
mapUnderscoreToCamelCase | 开启驼峰命名转换 | true/false | false |
lazyLoadingEnabled | 延迟加载的全局开关 | true/false | false |
cacheEnabled | 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存 | true/false | true |
defaultStatementTimeout | 设置超时时间 | 任意正整数 | 未设置 |
4. 映射文件(Mapper)详解
4.1 基本映射文件结构
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- 这里写SQL映射 -->
</mapper>
4.2 实体类示例
public class User {
private Long id;
private String username;
private String password;
private String email;
private Date createTime;
// 构造方法
public User() {}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
// getter和setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
// ... 其他getter/setter方法
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", createTime=" + createTime +
'}';
}
}
4.3 Mapper接口
public interface UserMapper {
// 根据ID查询用户
User selectById(Long id);
// 查询所有用户
List<User> selectAll();
// 添加用户
int insert(User user);
// 更新用户
int update(User user);
// 删除用户
int deleteById(Long id);
// 根据用户名查询
User selectByUsername(String username);
// 分页查询
List<User> selectByPage(@Param("offset") int offset, @Param("limit") int limit);
}
5. 基本CRUD操作
5.1 查询操作(Select)
<!-- 根据ID查询用户 -->
<select id="selectById" resultType="User">
SELECT id, username, password, email, create_time
FROM user
WHERE id = #{id}
</select>
<!-- 查询所有用户 -->
<select id="selectAll" resultType="User">
SELECT id, username, password, email, create_time
FROM user
ORDER BY create_time DESC
</select>
<!-- 根据用户名查询 -->
<select id="selectByUsername" resultType="User">
SELECT id, username, password, email, create_time
FROM user
WHERE username = #{username}
</select>
<!-- 分页查询 -->
<select id="selectByPage" resultType="User">
SELECT id, username, password, email, create_time
FROM user
ORDER BY create_time DESC
LIMIT #{offset}, #{limit}
</select>
5.2 插入操作(Insert)
<!-- 插入用户 -->
<insert id="insert" parameterType="User">
INSERT INTO user(username, password, email, create_time)
VALUES(#{username}, #{password}, #{email}, NOW())
</insert>
<!-- 插入用户并返回主键 -->
<insert id="insertAndReturnKey" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user(username, password, email, create_time)
VALUES(#{username}, #{password}, #{email}, NOW())
</insert>
<!-- 批量插入 -->
<insert id="insertBatch" parameterType="list">
INSERT INTO user(username, password, email, create_time)
VALUES
<foreach collection="list" item="user" separator=",">
(#{user.username}, #{user.password}, #{user.email}, NOW())
</foreach>
</insert>
5.3 更新操作(Update)
<!-- 更新用户 -->
<update id="update" parameterType="User">
UPDATE user
SET username = #{username},
password = #{password},
email = #{email}
WHERE id = #{id}
</update>
<!-- 动态更新(只更新不为空的字段) -->
<update id="updateSelective" parameterType="User">
UPDATE user
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="email != null and email != ''">
email = #{email},
</if>
</set>
WHERE id = #{id}
</update>
5.4 删除操作(Delete)
<!-- 根据ID删除用户 -->
<delete id="deleteById" parameterType="long">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 批量删除 -->
<delete id="deleteBatch" parameterType="list">
DELETE FROM user WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 根据条件删除 -->
<delete id="deleteByCondition">
DELETE FROM user
WHERE create_time < #{beforeDate}
</delete>
5.5 使用示例
public class UserService {
private SqlSession sqlSession;
private UserMapper userMapper;
public UserService() {
// 获取SqlSession
sqlSession = MyBatisUtils.getSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
}
// 查询用户
public User getUserById(Long id) {
return userMapper.selectById(id);
}
// 添加用户
public boolean addUser(User user) {
try {
int result = userMapper.insert(user);
sqlSession.commit(); // 提交事务
return result > 0;
} catch (Exception e) {
sqlSession.rollback(); // 回滚事务
e.printStackTrace();
return false;
}
}
// 关闭资源
public void close() {
if (sqlSession != null) {
sqlSession.close();
}
}
}
6. 参数传递详解
6.1 单个参数
<!-- 基本类型参数 -->
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 字符串参数 -->
<select id="selectByUsername" resultType="User">
SELECT * FROM user WHERE username = #{username}
</select>
// 接口方法
User selectById(Long id);
User selectByUsername(String username);
6.2 多个参数
方式1:使用@Param注解(推荐)
// 接口方法
List<User> selectByUsernameAndEmail(@Param("username") String username,
@Param("email") String email);
<select id="selectByUsernameAndEmail" resultType="User">
SELECT * FROM user
WHERE username = #{username} AND email = #{email}
</select>
方式2:使用Map传参
// 接口方法
List<User> selectByMap(Map<String, Object> params);
<select id="selectByMap" resultType="User">
SELECT * FROM user
WHERE username = #{username} AND email = #{email}
</select>
// 使用示例
Map<String, Object> params = new HashMap<>();
params.put("username", "admin");
params.put("email", "[email protected]");
List<User> users = userMapper.selectByMap(params);
方式3:使用实体对象传参
// 查询条件实体
public class UserQuery {
private String username;
private String email;
private Date startDate;
private Date endDate;
// getter/setter...
}
// 接口方法
List<User> selectByQuery(UserQuery query);
<select id="selectByQuery" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
<if test="startDate != null">
AND create_time >= #{startDate}
</if>
<if test="endDate != null">
AND create_time <= #{endDate}
</if>
</select>
6.3 集合参数
// 接口方法
List<User> selectByIds(@Param("ids") List<Long> ids);
int deleteBatch(@Param("ids") List<Long> ids);
<!-- 根据ID列表查询 -->
<select id="selectByIds" resultType="User">
SELECT * FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 批量删除 -->
<delete id="deleteBatch">
DELETE FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
7. 结果映射详解
7.1 基础结果映射
自动映射(列名与属性名一致)
<select id="selectById" resultType="User">
SELECT id, username, password, email FROM user WHERE id = #{id}
</select>
列名与属性名不一致的处理
方式1:使用别名
<select id="selectById" resultType="User">
SELECT
id,
username,
password,
email,
create_time AS createTime
FROM user
WHERE id = #{id}
</select>
方式2:开启驼峰命名转换