MyBatis CRUD 操作详解(完整版手册)
手册目录:
1.1 SqlSession 与 SqlSessionFactory

MyBatis 基础概念
1.1 SqlSession 与 SqlSessionFactory
-
SqlSessionFactory:通过mybatis-config.xml创建,负责生产SqlSession。 -
SqlSession:执行 SQL 的核心接口,提供 CRUD 方法。 -
完整写法示例:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User user = sqlSession.selectOne("com.example.mapper.UserMapper.selectUserById", 1);
sqlSession.commit();
} finally {
sqlSession.close();
}
1.2 Mapper 接口与 Mapper XML
-
Mapper 接口定义方法,与 Mapper XML 的
id一一对应。 -
Mapper XML 文件包含 SQL 语句。
-
简写方式(接口 + XML):
public interface UserMapper {
User selectUserById(int id);
}
对应 XML:
<select id="selectUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
1.3 注解方式
-
简单 SQL 可直接在 Mapper 接口加注解:
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(int id);
1.4 #{} 与 ${} 区别
-
#{}:预编译占位符,安全,防止 SQL 注入。 -
${}:直接文本替换,适合动态表名、列名,容易 SQL 注入。
2. 查询操作(Select)
2.1 完整写法
// 查询单条记录
User user = sqlSession.selectOne("com.example.mapper.UserMapper.selectUserById", 1);
// 查询多条记录
List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.selectAllUsers");
2.2 Mapper 接口简写方式
public interface UserMapper {
User selectUserById(int id);
List<User> selectAllUsers();
}
// 调用
User user = userMapper.selectUserById(1);
List<User> users = userMapper.selectAllUsers();
2.3 单参数、对象参数、集合参数
-
单参数:
User getUserById(@Param("id") int id);
-
对象参数:
User getUser(User user);
-
List 参数:
List<User> getUsersByIds(@Param("ids") List<Integer> ids);
2.4 动态 SQL 查询
<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
2.5 注意事项
-
selectOne只能返回单条记录,返回多条会抛异常。 -
selectList可返回多条记录。 -
参数类型必须与 Mapper 中定义匹配。
-
Mapper XML 或注解 SQL 的
id要对应正确。
3. 插入操作(Insert)
3.1 完整写法
User user = new User(1, "Alice");
int result = sqlSession.insert("com.example.mapper.UserMapper.insertUser", user);
sqlSession.commit();
3.2 Mapper 简写方式
public interface UserMapper {
int insertUser(User user);
}
// 调用
userMapper.insertUser(user);
3.3 自增主键获取
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users(name, age) VALUES(#{name}, #{age})
</insert>
3.4 批量插入
<insert id="insertUsers" parameterType="java.util.List">
INSERT INTO users(name, age) VALUES
<foreach collection="list" item="user" separator=",">
(#{user.name}, #{user.age})
</foreach>
</insert>
3.5 注意事项
-
必须提交事务。
-
返回值为影响行数。
-
自增主键需要配置
useGeneratedKeys。 -
默认 需要手动 commit(非 Spring 环境)。
-
插入自增主键时,可在 Mapper 中使用
useGeneratedKeys="true"+keyProperty="id"获取生成的主键。
4. 更新操作(Update)
4.1 完整写法
User user = new User(1, "Bob");
int result = sqlSession.update("com.example.mapper.UserMapper.updateUserName", user);
sqlSession.commit();
4.2 Mapper 简写方式
public interface UserMapper {
int updateUserName(User user);
}
// 调用
userMapper.updateUserName(user);
4.3 批量更新
<update id="updateUsers" parameterType="java.util.List">
<foreach collection="list" item="user">
UPDATE users SET name=#{user.name} WHERE id=#{user.id};
</foreach>
</update>
4.4 注意事项
-
更新操作务必带
WHERE条件,避免全表更新。 -
返回值为影响行数。
-
#{}占位符安全传参,${}不推荐直接使用。
5. 删除操作(Delete)
5.1 完整写法
int result = sqlSession.delete("com.example.mapper.UserMapper.deleteUserById", 1);
sqlSession.commit();
5.2 Mapper 简写方式
public interface UserMapper {
int deleteUserById(int id);
}
// 调用
userMapper.deleteUserById(1);
5.3 逻辑删除实现
<update id="deleteUserLogic">
UPDATE users SET deleted = 1 WHERE id = #{id}
</update>
5.4 注意事项
-
返回值为影响行数。
-
删除操作必须带条件,避免全表删除。
-
支持逻辑删除(更新状态)更安全。
6. 参数传递详解
| 类型 | 写法示例 | 注意事项 |
|---|---|---|
| 单个参数 | #{id} | 安全 |
| 多个参数 | @Param("id") int id, @Param("name") String name | 绑定参数必须对应 SQL 中变量 |
| 对象参数 | #{user.id}, #{user.name} | 支持对象属性访问 |
| Map 参数 | #{map.key} | Map key 必须对应 SQL |
| List 参数 | <foreach collection="list" item="id">#{id}</foreach> | 循环生成 SQL,注意分隔符 |
7. 动态 SQL 与高级查询
7.1 if / choose / where / set
<where>
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</where>
7.2 foreach 循环
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
7.3 bind 绑定变量
<bind name="pattern" value="'%' + name + '%'"/>
AND name LIKE #{pattern}
8. 事务管理
-
手动事务:
sqlSession.commit();
sqlSession.rollback();
-
Spring 事务管理:
@Transactional
public void updateUser(User user) { ... }
9. 性能优化
-
批量操作:减少 SQL 交互次数
-
一级缓存:同一个 SqlSession 内缓存
-
二级缓存:Mapper 级别缓存
-
延迟加载:延迟加载关联对象
| 操作 | 完整写法 | Mapper 接口简写 | 注意事项 |
|---|---|---|---|
| 查询 | selectOne/selectList | Mapper 方法直接调用 | selectOne 返回单条,selectList 返回多条 |
| 插入 | sqlSession.insert(...); commit(); | Mapper 方法直接调用 | 返回影响行数,自增主键需配置 keyProperty |
| 更新 | sqlSession.update(...); commit(); | Mapper 方法直接调用 | 注意 WHERE 条件,返回影响行数 |
| 删除 | sqlSession.delete(...); commit(); | Mapper 方法直接调用 | 必须带条件,推荐逻辑删除 |
| 参数传递 | @Param 或对象属性 | Mapper 方法参数直接传 | 使用 #{} 安全,避免 ${} 直接拼接 |

MyBatis CRUD 项目参考
1. 项目目录结构(参考)
mybatis-crud-demo/
├─ src/main/java/com/example/mybatisdemo/
│ ├─ MyBatisDemoApplication.java # Spring Boot 主类
│ ├─ entity/
│ │ ├─ User.java # User 实体类
│ │ └─ Order.java # Order 实体类示例
│ ├─ mapper/
│ │ ├─ UserMapper.java # User Mapper 接口
│ │ ├─ OrderMapper.java # Order Mapper 接口
│ │ └─ xml/
│ │ ├─ UserMapper.xml # User Mapper XML
│ │ └─ OrderMapper.xml # Order Mapper XML
│ ├─ service/
│ │ ├─ UserService.java
│ │ └─ OrderService.java
│ └─ controller/
│ ├─ UserController.java
│ └─ OrderController.java
├─ src/main/resources/
│ ├─ application.yml # 数据库 + MyBatis 配置
│ └─ mapper/
│ ├─ UserMapper.xml
│ └─ OrderMapper.xml
└─ pom.xml # Maven依赖
2. 示例数据库表结构
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT,
email VARCHAR(100),
deleted TINYINT DEFAULT 0
);
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
product_name VARCHAR(100),
price DECIMAL(10,2),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
3. 实体类示例
User.java
package com.example.mybatisdemo.entity;
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer deleted;
// Getter / Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Integer getDeleted() { return deleted; }
public void setDeleted(Integer deleted) { this.deleted = deleted; }
}
4. Mapper 接口示例(简写方式)
UserMapper.java
package com.example.mybatisdemo.mapper;
import com.example.mybatisdemo.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
// 查询
@Select("SELECT * FROM users WHERE id = #{id} AND deleted=0")
User selectUserById(@Param("id") Long id);
@Select("SELECT * FROM users WHERE deleted=0")
List<User> selectAllUsers();
// 插入
@Insert("INSERT INTO users(name, age, email) VALUES(#{name}, #{age}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertUser(User user);
// 更新
@Update("UPDATE users SET name=#{name}, age=#{age}, email=#{email} WHERE id=#{id} AND deleted=0")
int updateUser(User user);
// 逻辑删除
@Update("UPDATE users SET deleted=1 WHERE id=#{id}")
int deleteUserById(@Param("id") Long id);
// 动态查询
@Select("<script>" +
"SELECT * FROM users " +
"<where>" +
"<if test='name != null'>AND name LIKE CONCAT('%', #{name}, '%')</if>" +
"<if test='age != null'>AND age=#{age}</if>" +
"AND deleted=0" +
"</where>" +
"</script>")
List<User> searchUsers(@Param("name") String name, @Param("age") Integer age);
}
5. Mapper XML 示例(可选复杂 SQL)
UserMapper.xml
<?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.mybatisdemo.mapper.UserMapper">
<select id="selectAllUsers" resultType="com.example.mybatisdemo.entity.User">
SELECT * FROM users WHERE deleted=0
</select>
<insert id="insertUser" parameterType="com.example.mybatisdemo.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users(name, age, email) VALUES(#{name}, #{age}, #{email})
</insert>
<update id="updateUser" parameterType="com.example.mybatisdemo.entity.User">
UPDATE users
<set>
<if test="name != null">name=#{name},</if>
<if test="age != null">age=#{age},</if>
<if test="email != null">email=#{email}</if>
</set>
WHERE id=#{id} AND deleted=0
</update>
<update id="deleteUserById" parameterType="long">
UPDATE users SET deleted=1 WHERE id=#{id}
</update>
</mapper>
6. Service 层示例
UserService.java
package com.example.mybatisdemo.service;
import com.example.mybatisdemo.entity.User;
import com.example.mybatisdemo.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper){
this.userMapper = userMapper;
}
public User getUserById(Long id){
return userMapper.selectUserById(id);
}
public List<User> getAllUsers(){
return userMapper.selectAllUsers();
}
@Transactional
public void addUser(User user){
userMapper.insertUser(user);
}
@Transactional
public void updateUser(User user){
userMapper.updateUser(user);
}
@Transactional
public void deleteUser(Long id){
userMapper.deleteUserById(id);
}
public List<User> searchUsers(String name, Integer age){
return userMapper.searchUsers(name, age);
}
}
7. Controller 示例
UserController.java
package com.example.mybatisdemo.controller;
import com.example.mybatisdemo.entity.User;
import com.example.mybatisdemo.service.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService){
this.userService = userService;
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id){
return userService.getUserById(id);
}
@GetMapping
public List<User> getAllUsers(){
return userService.getAllUsers();
}
@PostMapping
public void createUser(@RequestBody User user){
userService.addUser(user);
}
@PutMapping
public void updateUser(@RequestBody User user){
userService.updateUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id){
userService.deleteUser(id);
}
@GetMapping("/search")
public List<User> searchUsers(@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age){
return userService.searchUsers(name, age);
}
}
8. 配置文件示例
application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.mybatisdemo.entity
configuration:
map-underscore-to-camel-case: true
9. 注意事项与最佳实践
-
参数安全
-
默认使用
#{},避免 SQL 注入。 -
${}仅用于表名、列名、排序字段。
-
-
事务管理
-
Spring Boot 推荐
@Transactional。 -
MyBatis 原生
SqlSession需要手动 commit/rollback。
-
-
逻辑删除
-
避免物理删除,全表删除危险。
-
-
动态 SQL
-
<if>,<where>,<set>,<foreach>可避免拼接错误。
-
-
批量操作
-
使用
<foreach>或 batch executor 提高性能。
-
-
缓存优化
-
一级缓存:同 SqlSession 内部自动缓存。
-
二级缓存:Mapper 级别,需要配置。
-
-
分页
-
可以使用 PageHelper 插件,避免手写分页 SQL。
-
-
复杂查询
-
联表查询可返回 Map 或多结果映射。
-
1258



被折叠的 条评论
为什么被折叠?



